Python语法基础:面向对象2

面向对象

一.保护对象的属性

如果有一个对象,当需要对其进行修改属性时,有2种方法

  • 对象名.属性名 = 数据 ---->直接修改
  • 对象名.方法名() ---->间接修改

为了更好的保存属性安全,即不能随意修改,一般的处理方式为

  • 将属性定义为私有属性
  • 添加一个可以调用的方法,供调用
class People:
    def __init__(self,name):
        self.__name=name
    def getNmae(self):#提供调用私有属性的方法
        return self.__name
    def setName(self,newName):#提供更改私有属性的方法
        if len(newName)>=5:
            self.__name=newName
        else:
            print("太长了")
xiaoming=People('xiaoming')
xiaoming.setName("xiaohuang")
print(xiaoming.getNmae())

Python中没有像C++中public和private这些关键字来区别公有属性和私有属性

它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。

二.__del__()方法

当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法

class Animal:
    #c初始化方法
    def __init__(self,name):
        print("__init__方法被调用")
        self.__name=name
    #析构方法:当对象被删除时会自动被调用
    def __del__(self):
        print("__del__方法被调用")
        print("%s对象马上狗带。。"%self.__name)
dog=Animal("柯基")
del dog

class Animal:
    #c初始化方法
    def __init__(self,name):
        print("__init__方法被调用")
        self.__name=name
    #析构方法:当对象被删除时会自动被调用
    def __del__(self):
        print("__del__方法被调用")
        print("%s对象马上狗带。。"%self.__name)
cat=Animal("橘猫")
cat2=cat
cat3=cat
del cat
del cat2
del cat3

  • 当有1个变量保存了对象的引用时,此对象的引用计数就会加1
  • 当使用del删除变量指向的对象时,如果对象的引用计数不为1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除

三.单继承

class Cat(object):
    def __init__(self,name,color="白色"):
        self.name=name
        self.color=color
    def run(self):
        print("%s再跑"%self.name)
class Bosi(Cat):
    def setNewName(self,newName):
        self.name=newName
    def eat(self):
        print("%s在吃"%self.name)
bs=Bosi("小七")
print(bs.name)
print(bs.color)
bs.run()
bs.setNewName("小红")
bs.eat()

  • 虽然子类没有定义__init__方法,但是父类有,所以在子类继承父类的时候这个方法就被继承了,所以只要创建Bosi的对象,就默认执行了那个继承过来的__init__方法
  • 子类在继承的时候,在定义类时,小括号()中为父类的名字
  • 父类的属性、方法,会被继承给子类
class Animal(object):

    def __init__(self, name='动物', color='白色'):
        self.__name = name
        self.color = color

    def __test(self):
        print(self.__name)
        print(self.color)

    def test(self):
        print(self.__name)
        print(self.color)



class Dog(Animal):
    def dogTest1(self):
        #print(self.__name) #不能访问到父类的私有属性
        print(self.color)


    def dogTest2(self):
        #self.__test() #不能访问父类中的私有方法
        self.test()


A = Animal()
#print(A.__name) #程序出现异常,不能访问私有属性
print(A.color)
#A.__test() #程序出现异常,不能访问私有方法
A.test()

print("------分割线-----")

D = Dog(name = "小花狗", color = "黄色")
D.dogTest1()
D.dogTest2()
  • 私有的属性,不能通过对象直接访问,但是可以通过方法访问
  • 私有的方法,不能通过对象直接访问
  • 私有的属性、方法,不会被子类继承,也不能被访问
  • 一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用

 四.多继承

所谓多继承,即子类有多个父类,并且具有它们的特征

class A:
    def printA(self):
        print('----A----')

# 定义一个父类
class B:
    def printB(self):
        print('----B----')

# 定义一个子类,继承自A、B
class C(A,B):
    def printC(self):
        print('----C----')

obj_C = C()
obj_C.printA()
obj_C.printB()

  • python中是可以多继承的
  • 父类中的方法、属性,子类会继承

当父类A与父类B有一个同名的方法,调用时谁在前就调谁

class base(object):
    def test(self):
        print('----base test----')
class A(base):
    def test(self):
        print('----A test----')
# 定义一个父类
class B(base):
    def test(self):
        print('----B test----')
# 定义一个子类,继承自A、B
class C(A,B):
    pass

obj_C = C()
obj_C.test()

print(C.__mro__) #可以查看C类的对象搜索方法时的先后顺序

五.重写父类方法与调用父类方法

1.重写

所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法

class Dog(object):
    def eat(self):
        print("我在吃狗粮")
class Corgi(Dog):
    def eat(self):
        print("我在吃饭饭")
xiaoqi=Corgi()
xiaoqi.eat()

2.调用父类方法

#coding=utf-8
class Cat(object):
    def __init__(self,name):
        self.name = name
        self.color = 'yellow'


class Bosi(Cat):
    def __init__(self,name):
        # 调用父类的__init__方法1(python2)
        #Cat.__init__(self,name)
        # 调用父类的__init__方法2
        #super(Bosi,self).__init__(name)
        # 调用父类的__init__方法3
        super().__init__(name)

    def getName(self):
        return self.name

bosi = Bosi('xiaohua')

print(bosi.name)
print(bosi.color)

六.多态

所谓多态:定义时的类型和运行时的类型不一样,此时就称为多态

class F1(object):
    def show(self):
        print('F1.show')

class S1(F1):

    def show(self):
        print('S1.show')

class S2(F1):

    def show(self):
        print('S2.show')

def Func(obj):
    obj.show()

s1_obj = S1()
Func(s1_obj)

s2_obj = S2()
Func(s2_obj)

七.类属性,实例属性

1.类属性就是类对象所拥有的属性,它被所以类对象的实例对象所共有,在内存中只存在一个副本。对于公有的类属性,在类外可以通过类对象实例对象访问

 __age = 12     #私有的类属性

p = People()

print(p.name)           #正确
print(People.name)      #正确
print(p.__age)            #错误,不能在类外通过实例对象访问私有的类属性
print(People.__age)        #错误,不能在类外通过类对象访问私有的类属性

2.实例属性

class People(object):
    address = '山东' #类属性
    def __init__(self):
        self.name = 'xiaowang' #实例属性
        self.age = 20 #实例属性

p = People()
p.age =12 #实例属性
print(p.address) #正确
print(p.name)    #正确
print(p.age)     #正确

print(People.address) #正确
print(People.name)    #错误
print(People.age)     #错误

通过实例(对象)去修改类属性

class People(object):
    address = '山东' #类属性
    def __init__(self):
        self.name = 'xiaowang' #实例属性
        self.age = 20 #实例属性

p = People()
p.age =12 #实例属性
print(p.address) #正确
print(p.name)    #正确
print(p.age)     #正确

print(People.address) #正确
print(People.name)    #错误
print(People.age)     #错误

  • 如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。 八.静态方法与类方法

八.静态方法与类方法

1).类方法

是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一个参数的名字,就最好用'cls'了),能够通过实例对象和类对象去访问。

class People(object):
    country = 'china'
    #类方法,用classmethod来进行修饰
    @classmethod
    def getCountry(cls):
        return cls.country

p = People()
print(p.getCountry())   #可以用过实例对象引用
print(People.getCountry())    #可以通过类对象引用

类方法还有一个用途就是可以对类属性进行修改:

class People(object):
    country = 'china'
    #类方法,用classmethod来进行修饰
    @classmethod
    def getCountry(cls):
        return cls.country
    @classmethod
    def setCountry(cls,country):
        cls.country=country

p = People()
print(p.getCountry())   #可以用过实例对象引用
print(People.getCountry())    #可以通过类对象引用
p.setCountry('japen')
print(p.getCountry())
print(People.getCountry())

2).静态方法

需要通过修饰器@staticmethod来进行修饰,静态方法不需要定义参数

class People(object):
    country = 'china'

    @staticmethod
    #静态方法
    def getCountry():
        return People.country

print(People.getCountry())

从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用

猜你喜欢

转载自www.cnblogs.com/python-road/p/10488586.html