DAY33继承实现原理、子类调用父类的方法、封装
来源:互联网 发布:淘宝怎么下架商品 编辑:程序博客网 时间:2024/06/16 12:03
继承实现原理
python中的类可以同时继承多个父类,继承的顺序有两种:深度优先和广度优先。
一般来讲,经典类在多继承的情况下会按照深度优先的方式查找,新式类会按照广度优先的方式查找
示例解析:
没有共同头部父类的类型
class E: def test(self): print('from E') # passclass F: def test(self): print('from F') # passclass C: def test(self): print('from C') # passclass B(C): def test(self): print('from B') # passclass D(E): def test(self): print('from D') # passclass A(B,D,F): def test(self): print('from A') # passobj=A()obj.test()
在这种模型下,新式类和经典类的继承顺序都一样。
调用obj.test(),首先找boj对象的dict字典,然后找生成类A的dict字典,如果这两个都没有,会按照以下顺序进行查找,找到为止:
ClassA->ClassB->ClassC->ClassD->ClassE->ClassF
如果都找不到,抛出异常错误。
有共同头部父类的类型
class D(object): def test(self): print('from D') # passclass C(D): def test(self): print('from C') # passclass B(C): def test(self): print('from B') # passclass F(D): def test(self): print('from F') # passclass E(F): def test(self): print('from E') # passclass H(D): def test(self): print('from H') # passclass G(H): def test(self): print('from G') # passclass A(B,E,G): def test(self): print('from A') # passobj=A()obj.test()print(A.mro())
在这种模型下,新式类和经典类查找继承顺序不同。
新式类使用的是广度优先的方式,调用obj.test(),首先找boj对象的dict字典,然后找生成类A的dict字典,如果这两个都没有,会按照以下顺序进行查找,找到为止:
classA->classB->classC->classE->classF->classG->classH->classD->-classobject
#经典类不继承objectclass D: def test(self): print('from D') # passclass C(D): def test(self): print('from C') # passclass B(C): def test(self): print('from B') # passclass F(D): def test(self): print('from F') # passclass E(F): def test(self): print('from E') # passclass H(D): def test(self): print('from H') # passclass G(H): def test(self): print('from G') # passclass A(B,E,G): def test(self): print('from A') # passobj=A()obj.test()
经典类(python2中才有经典类的概念,python3中都是新式类)使用的是深度优先的方式,调用obj.test(),首先找boj对象的dict字典,然后找生成类A的dict字典,如果这两个都没有,会按照以下顺序进行查找,找到为止:
ClassA->ClassB->ClassC->ClassD->ClassE->ClassF->ClassG
mro方法
python的继承顺序,是按照一定的算法生成的mro表进行顺序查找继承的,只有在新式类中才有该方法:该方法有以下三个特点:
1.子类会先于父类被检查:
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类
例如示例二有共同头部父类的模型,新式类mro输出表如下,按照表顺序进行继承:
1 print(A.mro())
2 [
子类调用父类的方法(内置函数super)
low版调用方法,还是那个teacher还是那个people:
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__函数 self.salary=salary self.level=level def foo(self): print('from child')t=Teacher('bob',18,'male',3000,10)print(t.name,t.age,t.sex,t.salary,t.level)t.foo()
low版调用方法,在更改父类的名字之后,需要改动的地方除了子类继承的父类名字,还要改子类里面调用的父类名,比较麻烦
高端大气调用方式:只需要改动子类继承的父类名,即括号里的父类名
字
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): #在python3中 super().__init__(name,age,sex) #调用父类的__init__的功能,实际上用的是绑定方法,用到了mro表查询继承顺序,只能调用一个父类的功能 #在python2中 # super(Teacher,self).__init__(name,age,sex) #super(Teacher,self)是一个死格式 self.salary=salary self.level=level def foo(self): super().foo() print('from child')t=Teacher('bob',18,'male',3000,10)print(t.name,t.age,t.sex,t.salary,t.level)t.foo()
但是这种方式也有一个缺点,就是当一个子类继承了多个父类的时候,如果多个父类都包含了相同的属性名,当要调用该功能的时候,只能调用第一个父类的功能,无法实现多个父类同时调用。多个父类同时调用还是要用low版方法。
封装
封装是一种隐藏的方式,包括数据封装和功能封装,即类里的数据属性和功能属性,隐藏数据和功能是为了限制直接调用,通过人为的添加调用接口进行数据和功能的调用。
封装不是单纯意义的隐藏:(史上最lowB的解释)
1:封装数据的主要原因是:保护隐私(作为男人的你,脸上就写着:我喜欢男人,你害怕么?)
2:封装方法的主要原因是:隔离复杂度,提供简单的访问接口(快门就是傻瓜相机为傻瓜们提供的接口,该方法将内部复杂的照相功能都隐藏起来了,拍照只需要通过快门这个接口就可以了,再比如你不必知道你自己的尿是怎么流出来的,你直接掏出自己的接口就能用尿这个功能)
提示:在编程语言里,对外提供的接口(接口可理解为了一个入口),可以是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。
封装的两个层面
基础的封装(什么都不用做):创建类和对象会创建各自的名称空间,通过类名. 或者对象. 的方式去访问类或对象里面的数据属性和功能属性。
还是这个people
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def foo(self): print('from parent')print(People.__dict__)p=People('natasha',18,'female')print(p.name)p.foo()
通过p.name访问到了natasha,通过p.age访问到了18,这一类就是最基础的类和对象的封装,而p.name、p.foo()就是接口,访问数据属性和功能属性的接口。
二层封装:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。
封装方式:在python中用双下划线的方式实现隐藏属性(设置成私有的)
class Teacher: __school='oldboy' #实际上转换成了_Teacher__school def __init__(self,name,salary): self.name=name self.__salary=salary #实际上转换成了self._Teacher__salary def __foo(self): print('====foo====')t=Teacher('egon',3000)# print(t.__school) #无法调用print(Teacher.__dict__) # t.foo() #无法调用t._Teacher__foo()# print(t.salary) #无法调用# print(t.__salary) #无法调用print(t.__dict__)print(t._Teacher__salary)
基础类里面的函数
封装数据
__数据属性
封装功能
这种变形操作,只在类的定义阶段发生或者对象定义阶段
在类的外部无法直接使用变形的属性,但是在类中可以直接使用
- DAY33继承实现原理、子类调用父类的方法、封装
- 子类继承和调用父类的构造方法
- 子类继承和调用父类的构造方法
- 子类继承和调用父类的构造方法
- 子类继承和调用父类的构造方法
- 子类继承和调用父类的构造方法
- 继承、访问控制符、子类重载父类的方法、子类调用父类的方法
- 【Java笔记】继承父类的方法可以调用子类的方法(子类必须在重写相应方法)
- C#中子类调用父类的实现方法
- Python实现子类调用父类的方法
- python子类调用父类的构造方法实现方案
- 子类继承父类的static方法
- 子类继承父类的构造方法
- java中子类继承父类方法及调用规则
- leetcode:Peeking Iterator 迭代器继承,父类调用子类方法
- JavaScript 子类调用父类构造器实现继承
- 子类继承的父类的protected方法能否被其他类调用深度解析
- 继承的顺序,子类覆盖继承父类的方法
- TestNG+Selenium Webdriver 数据(Excel)驱动的方法
- AFN 判断网络连接类型
- [awk]练习1
- bzoj2662: [BeiJing wc2012]冻结
- C内存管理
- DAY33继承实现原理、子类调用父类的方法、封装
- LeetCode#6 ZigZag Conversion
- python3.5 安装python3-tk
- BottomNavigationBar底部导航栏
- Windows13
- [贪心 构造] SRM 717 div1 ScoresSequence
- Windows14
- 工厂方法模式
- Windows下的Django安装与环境配置