---恢复内容开始---
在Python中继承顺序有两种:深度优先和广度优先
没有共同父类的继承:
class E: def test(self): print('from E') class A(E): #步骤4 A(E) #from E # def test(self): # print('from A') #步骤2 from B pass class B: # def test(self): # print('from B') #步骤3 from C pass class C: # def test(self): # print('from C') pass class D(A,B,C): # def test(self): # print('from D') #步骤1 from A pass t=D() #实例化对象t t.test()
这种类型的继承新式类和经典类的顺序是一样的都是深度优先:D--->A--->E--->B--->C
共同父类的继承
class D(object): def test(self): print('from D') # pass class C(D): def test(self): print('from C') # pass class B(C): def test(self): print('from B') # pass class F(D): def test(self): print('from F') # pass class E(F): def test(self): print('from E') # pass class H(D): def test(self): print('from H') # pass class G(H): def test(self): print('from G') # pass class A(B,E,G): def test(self): print('from A') # pass obj=A() obj.test() print(A.mro())
#经典类不继承object class D: def test(self): print('from D') # pass class C(D): def test(self): print('from C') # pass class B(C): def test(self): print('from B') # pass class F(D): def test(self): print('from F') # pass class E(F): def test(self): print('from E') # pass class H(D): def test(self): print('from H') # pass class G(H): def test(self): print('from G') # pass class A(B,E,G): def test(self): print('from A') # pass obj=A() obj.test()
在这种类型继承下新式类和经典类的顺序不同。
新式类采取广度优先:A--->B--->C--->E--->F--->G--->H--->D--->object
经典类(python2中才有经典类的概念,python3中都是新式类)使用的是深度优先的方式A--->B--->C--->D--->E--->F--->G
mro():
只有新式类才具有的方法
print(A.mro()) 执行结果 [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class '__main__.G'>,
<class '__main__.H'>, <class '__main__.D'>, <class 'object'>]
可以通过该方法来查看父类的继承顺序
子类调用父类的两种方法:
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,level,salary): # People.__init__(self,name,age,sex) #方法一 super().__init__(name,age,sex) #super(Teacher,self).__init__(name,age,sex) #方法二 self.level=level self.salary=salary def foo(self): super().foo() print('from child')
封装
封装是一种隐藏的方式,包括数据封装和功能封装,即类里的数据属性和功能属性,隐藏数据和功能是为了限制直接调用,通过人为的添加调用接口进行数据和功能的调用
封装的变形操作只在类的定义阶段或者对象的实例化阶段
封装的主要原因:
1.保护隐私
2.隔离复杂度,提供简单的接口
class Teacher: def __init__(self,name,salary): self.name=name self.__salary=salary def foo(self): print('balabala',self.__salary) t=Teacher('xiaolan',5000) print(t.salary) 执行结果 AttributeError: 'Teacher' object has no attribute 'salary'
print(t.__dict__) print(t._Teacher__salary) t.foo() 执行结果 {'name': 'xiaolan', '_Teacher__salary': 5000} 5000 balabala 5000
class A: def foo(self): print('from A.foo') self.__bar() def __bar(self): print('from A.bar') class B(A): def bar(self): print('from B.bar') pass b=B() b.foo() 执行结果 from A.foo from A.bar
在封装后对象的数据属性和函数属性以‘_类名__属性’名的形式保存
class Foo: def __func(self): #_Foo__func print('from Foo') class Bar(Foo): def __func(self): #_Bar__func print('from Bar') b=Bar() b._Foo__func() b._Bar__func()
在父类和子类有相同的属性时不会担心子类的属性将父类的属性覆盖调用
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 #name、age、sex、height、weight都是经过封装后保存,所以外部调用的时候没办法直接调用 def tell_name(self): print(self.__name) #通过手动创建接口的方式返回name的内容,屏蔽了直接调用 def set_name(self,val): if not isinstance(val,str): raise TypeError('type must be str') self.__name=val #通过手动创建修改接口修改name的属性值,屏蔽了直接调用 def tell_info(self): print(''' ---------%s info name:%s age:%s sex:%s height:%s weight:%s ''' %(self.__name, self.__name, self.__age, self.__sex, self.__height, self.__weight)) #通过手动创建接口,展示所有的信息
property:封装的特性之一
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值,可以讲函数功能的执行伪装为数据属性
property的构造方法中有个四个参数
- 第一个参数是方法名,调用
对象.属性
时自动触发执行方法 - 第二个参数是方法名,调用
对象.属性 = XXX
时自动触发执行方法 - 第三个参数是方法名,调用
del 对象.属性
时自动触发执行方法 - 第四个参数是字符串,调用
对象.属性.__doc__
,此参数是该属性的描述信息
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 @property #bmi=property(bmi),是一个内置函数,本质就是个装饰器 def bmi(self): res=self.__weight / (self.__height ** 2) return res
xiaobai=People('xiaobai',22,'male',1.80,67)
print(xiaobai.bmi)
执行结果
20.679012345679013
class People: def __init__(self,name,age,sex,height,weight,permission=False): self.__name=name self.__age=age self.__sex=sex self.__height=height self.__weight=weight self.permission=permission @property def name(self): return self.__name @name.setter #支持obj.name='NAME'的方式执行 def name(self,val): if not isinstance(val,str): raise TypeError('must be str') self.__name=val @name.deleter #支持del删除操作 def name(self): if not self.permission: raise PermissionError('不让删') del self.__name xiaobai=People('xiaobai',22,'male',1.80,67) print(xiaobai.name) xiaobai.name='xiaobai Lyn' print(xiaobai.__dict__) xiaobai.permission=True del xiaobai.name print(xiaobai.__dict__) 执行结果 xiaobai {'_People__name': 'xiaobai Lyn', '_People__age': 22, '_People__sex': 'male', '_People__height': 1.8, '_People__weight': 67, 'permission': False} {'_People__age': 22, '_People__sex': 'male', '_People__height': 1.8, '_People__weight': 67, 'permission': True}
class Foo: def get_bar(self): return 'xiaobai' # *必须两个参数 def set_bar(self, value): return 'set value' + value def del_bar(self): return 'xiaobai' BAR = property(get_bar, set_bar, del_bar, 'description...') obj = Foo() obj.BAR # 自动调用第一个参数中定义的方法:get_bar obj.BAR = "youzi" # 自动调用第二个参数中定义的方法:set_bar方法,并将“youzi”当作参数传入 del Foo.BAR # 自动调用第三个参数中定义的方法:del_bar方法 obj.BAE.__doc__ # 自动获取第四个参数中设置的值:description...