面向对象三大特性

封装

继承

多态

多个不同的类具有共同的方法f,各个类调用方法f,返回值不同。把方法f提取出来,封装为一个接口g。不同类的实例作为参数,传入接口g,得到不同返回值。

classDog:deftalk(self):print('汪汪汪...')classCat:deftalk(self):print('喵喵喵...')classBird:deftalk(self):print('叽叽喳喳...')defprint_talk(obj):

obj.talk()if __name__ == '__main__':

d=Dog()

c=Cat()

b=Bird()

print_talk(d)#汪汪汪...

print_talk(c) #喵喵喵....

print_talk(b) #叽叽喳喳...

View Code

Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。

classFather:pass

classS1(Father):defshow(self):print('in S1 func show')classS2(Father):defshow(self):print('in S2 func show')#由于在Java或C#中定义函数参数时,必须指定参数的类型#为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类#而实际传入的参数是:S1对象和S2对象

defFunc(F obj):"""Func函数需要接收一个F1类型或者F1子类的类型"""obj.show()

s1_obj=S1()

Func(s1_obj)#在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show

s2_obj=S2()

Func(s2_obj)#在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show

Python伪代码实现Java或C#的多态

super

在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如:

classAnimal(object):def __init__(self, name):

self.name=namedefeat(self):print('in Animal, eat func')classDog(Animal):defeat(self):

super(Dog, self).eat()print('in Dog, eat func')if __name__ == '__main__':

d= Dog('大黄')

d.eat()'''in Animal, eat func

in Dog, eat func'''

子类重写父类方法

看了上面的使用,你可能会觉得 super 的使用很简单,无非就是获取了父类,并调用父类的方法。其实,在上面的情况下,super 获得的类刚好是父类,但在其他情况就不一定了,super 其实和父类没有实质性的关联。

classBase(object):def __init__(self):print('enter Base')print('leave Base')classA(Base):def __init__(self):print('enter A')

super().__init__()print('leave A')classB(Base):def __init__(self):print('enter B')

super().__init__()print('leave B')classC(A, B):def __init__(self):print('enter C')

super().__init__()print('leave C')if __name__ == '__main__':

c=C()print(C.mro())'''enter C

enter A

enter B

enter Base

leave Base

leave B

leave A

leave C

[, , , , ]'''

super 多重继承

如果你认为 super 代表『调用父类的方法』,那你很可能会疑惑为什么 enter A 的下一句不是 enter Base 而是 enter B。原因是,super 和父类没有实质性的关联,现在让我们搞清 super 是怎么运作的。

事实上,对于你定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表,它代表了类继承的顺序,我们可以使用mro()获得某个类的 MRO 列表。

那这个 MRO 列表的顺序是怎么定的呢,它是通过一个 C3 线性化算法来实现的,这里我们就不去深究这个算法了,感兴趣的读者可以自己去了解一下,总的来说,一个类的 MRO 列表就是合并所有父类的 MRO 列表,并遵循以下三条原则:

子类永远在父类前面

如果有多个父类,会根据它们在列表中的顺序被检查

如果对下一个类存在两个合法的选择,选择第一个父类

super 的工作原理如下:

defsuper(cls, inst):

mro= inst.__class__.mro()return mro[mro.index(cls) + 1]

其中,cls 代表类,inst 代表实例,上面的代码做了两件事:

获取 inst 的 MRO 列表

查找 cls 在当前 MRO 列表中的 index, 并返回它的下一个类,即 mro[index + 1]

当你使用 super(cls, inst) 时,Python 会在 inst 的 MRO 列表上搜索 cls 的下一个类。

现在,让我们回到前面的例子。

首先看类 C 的 __init__ 方法:

这里的 self 是当前 C 的实例,self.__class__.mro() 结果是:

可以看到,C 的下一个类是 A,于是,跳到了 A 的 __init__,这时会打印出 enter A,并执行下面一行代码:

注意,这里的 self 也是当前 C 的实例,MRO 列表跟上面是一样的,搜索 A 在 MRO 中的下一个类,发现是 B,于是,跳到了 B 的 __init__,这时会打印出 enter B,而不是 enter Base。

整个过程还是比较清晰的,关键是要理解 super 的工作方式,而不是想当然地认为 super 调用了父类的方法。

5.小结

事实上,super 和父类没有实质性的关联。

super(cls, inst) 获得的是 cls 在 inst 的 MRO 列表中的下一个类。

C3算法

在python3中,所有的类都是新式类,继承顺序遵循广度优先的C3算法.

C3算法的规则如下:

每一个类的继承顺序都是从父类向子类看

形成一个指向关系的顺序[当前类]+[父类的继承顺序]

如果一个类出现在从左到右的第一个顺序上并且没有出现在后面顺序中或者出现在后面的顺序中但是仍然是第一顺序,那么就把这个类提取出来

例如下图:

由上图可知:B类,C类和D类是单继承,所以很容易看出L(B),L(C)和L(D)

L(B) = [BFGO]

L(C) = [CEO]  (注:python3中所有类都是新式类,默认继承object类)

L[D] = [DGO]

然后分析多继承的A类的继承顺序:

L(A) = L(B)+L(C)+L(D)

A     =[BFGO] + [CEO] + [DGO]

AB   = [FGO] + [CEO] + [DGO]

ABF =[GO] + [CEO] + [DGO]

ABFC = [GO] + [EO] + [DGO]

ABFCE = [GO] + [O] + [DGO]

ABFCED = [GO] + [O] + [GO]

ABFCEDG = [O] + [O] + [O]

L(A) = [ABFCEDGO]

结果A类的继承顺序就为A,B,F,C,E,D,G,object.

也可以通过类的__mro__属性来查看当前类的继承顺序

super内置函数的寻找顺序也与此顺序相同

#C3 定义引用开始

C3 算法:MRO是一个有序列表L,在类被创建时就计算出来。

L(Child(Base1,Base2)) = [ Child + merge( L(Base1) ,  L(Base2) ,  Base1Base2 )]

L(object) = [ object ]

L的性质:结果为列表,列表中至少有一个元素即类自己。

+        : 添加到列表的末尾,即 [ A + B ] = [ A,B ]

merge: ① 如果列表空则结束,非空 读merge中第一个列表的表头,

② 查看该表头是否在 merge中所有列表的表尾中。

②-->③ 不在,则 放入 最终的L中,并从merge中的所有列表中删除,然后 回到①中

②-->④ 在,查看 当前列表是否是merge中的最后一个列表

④-->⑤ 不是 ,跳过当前列表,读merge中下一个列表的表头,然后 回到 ②中

④-->⑥ 是,异常。类定义失败。

表头: 列表的第一个元素 (列表:ABC,那么表头就是A,B和C就是表尾)

表尾: 列表中表头以外的元素集合(可以为空)

merge 简单的说即寻找合法表头(也就是不在表尾中的表头),如果所有表中都未找到合法表头则异常。

#C3定义引用结束

例如:

L(D) = L(D(O))

= D + merge(L(O))

= D + O

= [D,O]

L(B) = L(B(D,E))

= B + merge(L(D) , L(E))

= B + merge(DO , EO) # 第一个列表DO的表头D,其他列表比如EO的表尾都不含有D,所以可以将D提出来,即D是合法表头

= B + D + merge(O , EO) #从第一个开始表头是O,但是后面的列表EO的表尾中含有O所以O是不合法的,所以跳到下一个列表EO

= B + D + E + merge(O , O)

= [B,D,E,O]

同理:

L(C) = [C,E,F,O]

L(A(B,C)) = A + merge(L(B),L(C),BC)

= A + merge(BDEO,CEFO,BC)#B是合法表头

= A + B + merge(DEO,CEFO,C)#D是合法表头

= A + B + D + merge(EO,CEFO,C)#E不是合法表头,跳到下一个列表CEFO,此时C是合法表头

= A + B + D + C + merge(EO,EFO)#由于第三个列表中的C被删除,为空,所以不存在第三个表,只剩下两个表;此时E是合法表头

= A + B + D + C + E + merge(O,FO)#O不是合法表头,跳到下一个列表FO,F是合法表头,

= A + B + D + C + E + F + merge(O,O)#O是合法表头

= A + B + D + C + E + F + O

= [A,B,D,C,E,F,O]

获取C3的数组列表,可以梳理清楚子类执行过程中向上执行的顺序

python登录面向对象_python基础 面向对象一相关推荐

  1. Python学习教程(Python学习路线_Python基础学习教程_Python视频教程):初学者新手怎样快速入门Python

    Python学习教程(Python学习路线_Python基础学习教程_Python视频教程):初学者新手怎样快速入门Python? 人生苦短,我用Python!!!短短几个字,现在在各大学习类平台随处 ...

  2. python基础程序设计与面向对象程序设计_python基础——面向对象的程序设计

    python基础--面向对象的程序设计 1 什么是面向对象的程序设计 面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...

  3. python面向过程还是面向对象_python是面向对象还是面向过程?

    python是面向对象的,第一个公开发行版发行于1991年,Python语法简洁而清晰,具有丰富和强大的类库. Python是一种面向对象.解释型计算机程序设计语言,由Guido van Rossum ...

  4. python 完全面向对象_python之面向对象

    Python Python开发 Python语言 python之面向对象 第一章 面向对象初识 面向对象的三大特性是什么? 抽象.继承.多态. 面向对象第一个优点:* 对相似功能的函数,同一个业务的函 ...

  5. cpython python 区别面试_python基础教程之千万不要错过这几道Python面试题

    第1题: python下多线程的限制以及多进程中传递参数的方式? python多线程有个全局解释器锁(global interpreter lock),简称GIL,这个GIL并不是python的特性, ...

  6. java基础面向对象_Java基础面向对象

    一.面向过程的思想和面向对象的思想 面向对象和面向过程的思想有着本质上的区别,作为面向对象的思维来说,当你拿到一个问题时,你分析这个问题不再是第一步先做什么,第二步再做什么,这是面向过程的思维,你应该 ...

  7. python数据分析知识点_Python基础知识点总结:数据

    首先, 什么是Python? 用python作者Guido van Rossum自己的话来说,Python是这样的一门语言: 它是一门高级编程语言, 它的核心设计理念是让所有代码变得更易阅读,并给开发 ...

  8. python的基本原理_python基础1(理论基础)

    1.python是什么语言 2.python的发展史 3.python2与python3的区别 4.python的语言类型 5.python的优缺点 6.IDLE是什么 7.变量是什么 一.pytho ...

  9. python登录豆瓣_python登录豆瓣并发帖的方法

    导读热词 本文实例讲述了python登录豆瓣并发帖的方法.分享给大家供大家参考.具体如下: 这里涉及urllib.urllib2及cookielib常用方法的使用 登录豆瓣,由于有验证码,采取的办法是 ...

最新文章

  1. 雷军 1994 年写的代码,经典老古董~
  2. 哈哈,netbeans5.5的Visual Web Pack终于出来了
  3. 前端dashboard框架_微前端在网易七鱼的实践
  4. 电路常识性概念(6)-VCC、VDD和VSS三种标号的区别
  5. 通过web.xml文件自动启动spring容器加载对应的配置文件
  6. mysql 1157_更新时出现MySQL错误1157,但是我在where子句中使用主键
  7. 【转】使用python进行多线程编程
  8. Linux下设计一个简单的线程池
  9. es使用pencentiles对网站访问延时统计
  10. 线程同步之条件变量和信号量(生产者消费者模型)
  11. python面向对象设计角色攻击_Python技能:面向对象基础实战之英雄联盟
  12. pingfang css,前端项目,引入PingFang SC字体
  13. 前馈-反馈控制系统设计(过程控制课程设计matlab/simulink)
  14. sublime text3 boxy主题 (本地 压缩包 安装)
  15. t3插密码狗不显示服务器,登陆T3时,用户名和账套都不显示,显示没有检测到合法的LISENCE,需要重新注册密码狗,在注册社区后,搜索.cjt的文件,搜不到...
  16. 常用工具类(一) 身份证+姓名+手机号码验证
  17. 直击|咪蒙、才华有限青年注销 旗下公众号清空或停更
  18. 净值继续回落,短期弱势难改
  19. Git版本控制管理——提交
  20. 平仓_敞口_外汇结售汇_小记

热门文章

  1. 【Linux_】权限
  2. HTMl页面加入落叶下雨动画,HTML5和Webkit实现树叶飘落动画
  3. Android开发是简单的「能写应用就行」吗?复习指南
  4. php 超过一行用省略号,php 超长用省略号代替
  5. 常见linux服务器存储空间,怎么在linux上查看服务器的存储空间多大
  6. 阿里云8核16G服务器ecs.c6.2xlarge性能评测CPU处理器型号
  7. 微信小程序基于百度云实现图文识别(胎教级教程)
  8. c语言精髓之编译过程,C语言精髓知识点
  9. 行业分析是什么?该怎么做?
  10. TPLINK TL-AP1300I-PoE功能失常导致网络故障一例