一.继承的实现原理
1.继承顺序
1.1单独分叉线路:经典类与新式类依次从左到右,深度优先
1.2多条重合线路:经典类一路到头,深度优先;新式类,广度优先。<参考MRO列表,仅在新式类有>
class A(object): def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B): def test(self): print('from D') class E(C): def test(self): print('from E') class F(D,E): # def test(self): # print('from F') pass f1=F() f1.test() print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性 #新式类继承顺序:F->D->B->E->C->A #经典类继承顺序:F->D->B->A->E->C #python3中统一都是新式类 #pyhon2中才分新式类与经典类
2.SUPER方法的应用<使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表>
子类调用父类的方法:
super()---->是一个对象,可以查看
方法一:
class Vehicle: #定义交通工具类 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦...') class Subway(Vehicle): #地铁 def __init__(self,name,speed,load,power,line): Vehicle.__init__(self,name,speed,load,power) self.line=line def run(self): print('地铁%s号线欢迎您' %self.line) Vehicle.run(self) line13=Subway('中国地铁','180m/s','1000人/箱','电',13) line13.run()
方法二:
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def foo(self): print('from parent') class Teacher(People): def __init__(self,name,age,sex,salary,level): # People.__init__(self,name,age,sex) #指名道姓地调用People类的__init__函数 #在python3中 super().__init__(name,age,sex) #调用父类的__init__的功能,实际上用的是绑定方法 #在python2中 # super(Teacher,self).__init__(name,age,sex) self.salary=salary self.level=level def foo(self): super().foo() print('from child') t=Teacher('egon',18,'male',3000,10) # print(t.name,t.age,t.sex,t.salary,t.level) t.foo()
3.访问限制
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
,在Python中,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
具体参考博客:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318650247930b1b21d7d3c64fe38c4b5a80d4469ad7000
4.property的使用
property装饰器,把装饰函数伪装成一个名词属性。
class People: def __init__(self, name, weight, height): self.name = name self.weight = weight self.height = height # @property def bmi(self): return self.weight / (self.height ** 2) f = People('egon', 70, 1.80) f.height=1.82 print(f.bmi()) #不加装饰器 #如果没有@property装饰器的话,调用函数属性就得f.bmi(),这样的接口给人一种明显的执行程序代码痕迹,而用 #该装饰器则直接调用f.bmi,更加方便客户的使用。 # print(f.bmi) #加装饰器后
与装饰器property连用的setter,deleter.
class People: def __init__(self,name,age,sex,height,weight): self.__name=name self.__age=age #此处都是私有属性,所以需要开放接口来让对象查看属性,因此才会用到相应的装饰器去修改和删除属性。 self.__sex=sex self.__height=height self.__weight=weight def tell_info(self): print(''' 姓名:%s 年龄:%s 性别:%s 高度:%scm 体重:%skg '''%(self.__name,self.__age,self.__sex,self.__height,self.__weight)) @property def name(self): #被property装饰器装饰后,可以直接调用name return self.__name @name.setter ##此处的name就是加上property装饰器后的name,该name.setter装饰器为了修改属性. def name(self,value): if not isinstance(value,str): raise TypeError('字符串格式') self.__name=value return self.__name @name.deleter ##此处的name就是加上property装饰器后的name,该name.deleter装饰器为了删除属性. def name(self): del self.__name @property def bmi(self): return self.__weight /(self.__height^2) p1=People('egon',18,'male',170,60) p1.tell_info() print(p1.name) p1.name='hason' #利用name.setter接口修改属性 del p1.name #利用name.deleter接口删除属性