Python 面向对象继承

一 什么是面向对象的继承

比较官方的说法就是:

继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。 一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。

字面意思就是:子承父业,合法继承家产,就是如果你是独生子,而且你也很孝顺,不出意外,你会继承你父母所有家产,他们的所有财产都会由你使用(败家子儿除外)。

那么用一个例子来看一下继承:

class Person:

def __init__(self,name,sex,age):

self.name = name

self.age = age

self.sex = sex

class Cat:

def __init__(self,name,sex,age):

self.name = name

self.age = age

self.sex = sex

class Dog:

def __init__(self,name,sex,age):

self.name = name

self.age = age

self.sex = sex

# 继承的用法:

class Aniaml(object):

def __init__(self,name,sex,age):

self.name = name

self.age = age

self.sex = sex

class Person(Aniaml):

pass

class Cat(Aniaml):

pass

class Dog(Aniaml):

pass

继承的有点也是显而易见的:

1,增加了类的耦合性(耦合性不宜多,宜精)。

2,减少了重复代码。

3,使得代码更加规范化,合理化。

二 继承的分类

就向上面的例子:

Aminal 叫做父类,基类,超类。 Person Cat Dog: 子类,派生类。 继承:可以分单继承,多继承。

这里需要补充一下python中类的种类(继承需要):

在python2x版本中存在两种类.:   ⼀个叫经典类. 在python2.2之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写.   ⼀个叫新式类. 在python2.2之后出现了新式类. 新式类的特点是基类的根是object类。 python3x版本中只有一种类: python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object

三 单继承

3.1 类名,对象执行父类方法

class Aniaml(object):

type_name = '动物类'

def __init__(self,name,sex,age):

self.name = name

self.age = age

self.sex = sex

def eat(self):

print(self)

print('吃东西')

class Person(Aniaml):

pass

class Cat(Aniaml):

pass

class Dog(Aniaml):

pass

# 类名:

print(Person.type_name) # 可以调用父类的属性,方法。

Person.eat(111)

print(Person.type_name)

# 对象:

# 实例化对象

p1 = Person('春哥','男',18)

print(p1.__dict__)

# 对象执行类的父类的属性,方法。

print(p1.type_name)

p1.type_name = '666'

print(p1)

p1.eat()

3.2 执行顺序

class Aniaml(object):

type_name = '动物类'

def __init__(self,name,sex,age):

self.name = name

self.age = age

self.sex = sex

def eat(self):

print(self)

print('吃东西')

class Person(Aniaml):

def eat(self):

print('%s 吃饭'%self.name)

class Cat(Aniaml):

pass

class Dog(Aniaml):

pass

p1 = Person('barry','男',18)

# 实例化对象时必须执行__init__方法,类中没有,从父类找,父类没有,从object类中找。

p1.eat()

# 先要执行自己类中的eat方法,自己类没有才能执行父类中的方法。

3.3 同时执行类以及父类方法

方法一:

如果想执行父类的func方法,这个方法并且子类中夜用,那么就在子类的方法中写上:

父类.func(对象,其他参数)

举例说明:

class Aniaml(object):

type_name = '动物类'

def __init__(self,name,sex,age):

self.name = name

self.age = age

self.sex = sex

def eat(self):

print('吃东西')

class Person(Aniaml):

def __init__(self,name,sex,age,mind):

'''

self = p1

name = '春哥'

sex = 'laddboy'

age = 18

mind = '有思想'

'''

# Aniaml.__init__(self,name,sex,age) # 方法一

self.mind = mind

def eat(self):

super().eat()

print('%s 吃饭'%self.name)

class Cat(Aniaml):

pass

class Dog(Aniaml):

pass

# 方法一: Aniaml.__init__(self,name,sex,age)

# p1 = Person('春哥','laddboy',18,'有思想')

# print(p1.__dict__)

# 对于方法一如果不理解:

# def func(self):

# print(self)

# self = 3

# func(self)

方法二:

利用super,super().func(参数)

class Aniaml(object):

type_name = '动物类'

def __init__(self,name,sex,age):

self.name = name

self.age = age

self.sex = sex

def eat(self):

print('吃东西')

class Person(Aniaml):

def __init__(self,name,sex,age,mind):

'''

self = p1

name = '春哥'

sex = 'laddboy'

age = 18

mind = '有思想'

'''

# super(Person,self).__init__(name,sex,age) # 方法二

super().__init__(name,sex,age) # 方法二

self.mind = mind

def eat(self):

super().eat()

print('%s 吃饭'%self.name)

class Cat(Aniaml):

pass

class Dog(Aniaml):

pass

# p1 = Person('春哥','laddboy',18,'有思想')

# print(p1.__dict__)

单继承的课堂练习

# 1

class Base:

def __init__(self, num):

self.num = num

def func1(self):

print(self.num)

class Foo(Base):

pass

obj = Foo(123)

obj.func1() # 123 运⾏的是Base中的func1

# 2

class Base:

def __init__(self, num):

self.num = num

def func1(self):

print(self.num)

class Foo(Base):

def func1(self):

print("Foo. func1", self.num)

obj = Foo(123)

obj.func1() # Foo. func1 123 运⾏的是Foo中的func1

# 3

class Base:

def __init__(self, num):

self.num = num

def func1(self):

print(self.num)

class Foo(Base):

def func1(self):

print("Foo. func1", self.num)

obj = Foo(123)

obj.func1() # Foo. func1 123 运⾏的是Foo中的func1

# 4

class Base:

def __init__(self, num):

self.num = num

def func1(self):

print(self.num)

self.func2()

def func2(self):

print("Base.func2")

class Foo(Base):

def func2(self):

print("Foo.func2")

obj = Foo(123)

obj.func1() # 123 Foo.func2 func1是Base中的 func2是⼦类中的

# 再来

class Base:

def __init__(self, num):

self.num = num

def func1(self):

print(self.num)

self.func2()

def func2(self):

print(111, self.num)

class Foo(Base):

def func2(self):

print(222, self.num)

lst = [Base(1), Base(2), Foo(3)]

for obj in lst:

obj.func2() # 111 1 | 111 2 | 222 3

# 再来

class Base:

def __init__(self, num):

self.num = num

def func1(self):

print(self.num)

self.func2()

def func2(self):

print(111, self.num)

class Foo(Base):

def func2(self):

print(222, self.num)

lst = [Base(1), Base(2), Foo(3)]

for obj in lst:

obj.func1() # 那笔来吧. 好好算

四 多继承

class ShenXian: # 神仙

def fei(self):

print("神仙都会⻜")

class Monkey: # 猴

def chitao(self):

print("猴⼦喜欢吃桃⼦")

class SunWukong(ShenXian, Monkey): # 孙悟空是神仙, 同时也是⼀只猴

pass

sxz = SunWukong() # 孙悟空

sxz.chitao() # 会吃桃⼦

sxz.fei() # 会⻜

此时, 孙悟空是⼀只猴⼦, 同时也是⼀个神仙. 那孙悟空继承了这两个类. 孙悟空⾃然就可以执⾏这两个类中的⽅法. 多继承⽤起来简单. 也很好理解. 但是多继承中, 存在着这样⼀个问题. 当两个⽗类中出现了重名⽅法的时候. 这时该怎么办呢? 这时就涉及到如何查找⽗类⽅法的这么⼀个问题.即MRO(method resolution order) 问题. 在python中这是⼀个很复杂的问题. 因为在不同的python版本中使⽤的是不同的算法来完成MRO的.

4.1经典类的多继承

虽然在python3中已经不存在经典类了. 但是经典类的MRO最好还是学⼀学. 这是⼀种树形结构遍历的⼀个最直接的案例. 在python的继承体系中. 我们可以把类与类继承关系化成⼀个树形结构的图. 来, 上代码:

class A:

pass

class B(A):

pass

class C(A):

pass

class D(B, C):

pass

class E:

pass

class F(D, E):

pass

class G(F, D):

pass

class H:

pass

class Foo(H, G):

pass

对付这种mro画图就可以:

继承关系图已经有了. 那如何进⾏查找呢? 记住⼀个原则. 在经典类中采⽤的是深度优先,遍历⽅案. 什么是深度优先. 就是⼀条路走到头. 然后再回来. 继续找下⼀个.

图中每个圈都是准备要送鸡蛋的住址. 箭头和⿊线表⽰线路. 那送鸡蛋的顺序告诉你入⼝在最下⾯R. 并且必须从左往右送. 那怎么送呢?

如图. 肯定是按照123456这样的顺序来送. 那这样的顺序就叫深度优先遍历. ⽽如果是142356呢? 这种被称为⼴度优先遍历. 好了. 深度优先就说这么多. 那么上⾯那个图怎么找的呢? MRO是什么呢? 很简单. 记住. 从头开始. 从左往右. ⼀条路跑到头, 然后回头. 继续⼀条路跑到头. 就是经典类的MRO算法.

类的MRO: Foo-> H -> G -> F -> E -> D -> B -> A -> C. 你猜对了么?

4.2 新式类的多继承

4.2.1 mro序列

class A:

pass

class B(A):

pass

class C(A):

pass

class D(B, C):

pass

class E:

pass

class F(D, E):

pass

class G(F, D):

pass

class H:

pass

class Foo(H, G):

pass

print(Foo.mro())

4.2.2 C3算法(不讲,自己了解)

MRO是一个有序列表L,在类被创建时就计算出来。 通用计算公式为:

mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )

(其中Child继承自Base1, Base2)

如果继承至一个基类:class B(A) 这时B的mro序列为

mro( B ) = mro( B(A) )

= [B] + merge( mro(A) + [A] )

= [B] + merge( [A] + [A] )

= [B,A]

如果继承至多个基类:class B(A1, A2, A3 …) 这时B的mro序列

mro(B) = mro( B(A1, A2, A3 …) )

= [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] )

= ...

计算结果为列表,列表中至少有一个元素即类自己,如上述示例[A1,A2,A3]。merge操作是C3算法的核心。

4.2.2. 表头和表尾

表头:   列表的第一个元素

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

示例   列表:[A, B, C]   表头是A,表尾是B和C

4.2.3. 列表之间的+操作

+操作:

[A] + [B] = [A, B] (以下的计算中默认省略) ---------------------

merge操作示例:

如计算merge( [E,O], [C,E,F,O], [C] )

有三个列表 : ① ② ③

1 merge不为空,取出第一个列表列表①的表头E,进行判断

各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表

2 取出列表②的表头C,进行判断

C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除

merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )

3 进行下一次新的merge操作 ......

---------------------

计算mro(A)方式:

mro(A) = mro( A(B,C) )

原式= [A] + merge( mro(B),mro(C),[B,C] )

mro(B) = mro( B(D,E) )

= [B] + merge( mro(D), mro(E), [D,E] ) # 多继承

= [B] + merge( [D,O] , [E,O] , [D,E] ) # 单继承mro(D(O))=[D,O]

= [B,D] + merge( [O] , [E,O] , [E] ) # 拿出并删除D

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

= [B,D,E,O]

mro(C) = mro( C(E,F) )

= [C] + merge( mro(E), mro(F), [E,F] )

= [C] + merge( [E,O] , [F,O] , [E,F] )

= [C,E] + merge( [O] , [F,O] , [F] ) # 跳过O,拿出并删除

= [C,E,F] + merge([O] , [O])

= [C,E,F,O]

原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])

= [A,B] + merge( [D,E,O], [C,E,F,O], [C])

= [A,B,D] + merge( [E,O], [C,E,F,O], [C]) # 跳过E

= [A,B,D,C] + merge([E,O], [E,F,O])

= [A,B,D,C,E] + merge([O], [F,O]) # 跳过O

= [A,B,D,C,E,F] + merge([O], [O])

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

---------------------

结果OK. 那既然python提供了. 为什么我们还要如此⿇烦的计算MRO呢? 因为笔 试.......你在笔试的时候, 是没有电脑的. 所以这个算法要知道. 并且简单的计算要会. 真是项⽬ 开发的时候很少有⼈这么去写代码.

这个说完了. 那C3到底怎么看更容易呢? 其实很简单. C3是把我们多个类产⽣的共同继 承留到最后去找. 所以. 我们也可以从图上来看到相关的规律. 这个要⼤家⾃⼰多写多画图就 能感觉到了. 但是如果没有所谓的共同继承关系. 那⼏乎就当成是深度遍历就可以了

什么是继承python_面向对象继承相关推荐

  1. python面向对象继承_Python 面向对象 --- 继承

    目标 单继承 多继承 面向对象三大特性 1,封装 根据 职责 将 属性 和 方法 封装 到以抽象的 类 中 2,继承 实现代码的重用,相同的代码不需要重复的缩写 3,多态 不同的对象调用相同的方法,产 ...

  2. python_day6_面向对象的介绍/构造函数/类变量和实例变量/析构函数/私有属性和私有方法/继承、多继承和继承实例/多态

    python_面向对象的介绍/构造函数/类变量和实例变量/析构函数/私有属性和私有方法/继承.多继承和继承实例/多态 在这里得感谢,老师Alex金角大王(路飞学城IT) Python(给兄弟们挂个

  3. java多态简单例子6_Java_6、面向对象——继承和多态

    继承 •继承是面向对象编程的三大特征之一,是一种基于已有类来创建新类的机制.由继承而得到的类称为子类(或派生类),被继承的类称为父类(或超类). •Java中每个类只允许有一个父类.语法如下:clas ...

  4. 类与面向对象的精华:继承【C++继承】

    引入继承 为什么需要继承? 简单举例 继承 定义 定性 is-a 而不是 has-a is-a has-a 语法 继承方式 继承方式影响了什么? 公有继承 public 私有继承 private 保护 ...

  5. Python之面向对象继承和派生

    Python之面向对象继承和派生 什么是继承: 继承是一种创建新的类的方法.在Python中,新建的类可以继承自一个或多个父类.原始类称为基类或超类. 新建的类称为派生类或子类. Python中类的继 ...

  6. C++ 面向对象(一)继承:继承、对象切割、菱形继承、虚继承、继承与组合

    目录 继承 继承的概念 继承方式 基类与派生类的赋值转换 作用域与隐藏 派生类的默认成员函数 友元与静态成员 友元 静态成员 多继承 菱形继承 虚继承 继承和组合 什么是组合 如何选择组合和继承 继承 ...

  7. 面向对象 - 继承/组合 - 总结

    面向对象 - 继承:1.继承: 类与类之间的关系 什么是什么的关系 eg:人是动物 狗是动物 功能: 解决代码重用问题, 创建新类的方式, 类: 可继承一个或多个父类: 父类 == 基类/超类 类 = ...

  8. Effective C++: 06继承与面向对象设计

    32:确定你的public继承塑模出is-a关系 以C++进行面向对象编程,最重要的一个规则是:public继承表示的是"is-a"(是一种)的关系. 如果令class D以pub ...

  9. JavaScript面向对象--继承 (超简单易懂,小白专属)...

    JavaScript面向对象--继承 (超简单易懂,小白专属) 一.继承的概念 子类共享父类的数据和方法的行为,就叫继承. 二.E55如何实现继承?探索JavaScript继承的本质 2.1构造函数之 ...

最新文章

  1. Dubbo作者亲述:那些辉煌、沉寂与重生的故事
  2. 依赖注入–字段vs构造函数vs方法
  3. 转:55个javascript处理网页技巧
  4. 时间加减计算器_小学生苦练加减乘除计算“基本功”,有没有必要?
  5. 不使用border-radius,实现一个可复用的高度和宽度都自适应的圆角矩形
  6. 开发环境ubuntu16.04(ubuntu18.04)安装以后的初始化设置
  7. Android4.1MediaPlayer无缝播放
  8. C#WinForm开发在选项卡tab中集成加载多个窗体,通过选项卡切换窗体(超详细讲解)
  9. 蒋文华《博弈论》笔记及视频摘录
  10. VS2013MFC对话框工程学习笔记二 - 了结布局和一些基本的窗口组件
  11. 2011年IT行业薪资调查报告
  12. Orcad 16.6中批量修改网络名
  13. bandit-Python代码审计工具
  14. .csv是什么文件格式,什么软件可以打开?xls与csv文件是什么区别?功能和作用上有什么不同?
  15. 7-4 sdust-Java-学生成绩读取与排序 (35分)CSDN-markdown编辑器
  16. JavaScript聊天器
  17. 运行cool edit时显示系统配置不正确
  18. 代码中超魔性图片注释
  19. 清除浏览器操作—JavaWeb网页刷新
  20. Python上位机,监视串口,逐字符匹配字头

热门文章

  1. matlab标准化和反标准化——zscore
  2. ZOJ 3381 Osaisen Choudai !
  3. 什么是ASR、TTS?
  4. C#工业触摸屏上位机源码 纯源代码 替代传统plc搭载的触摸屏
  5. 脱欧导致IT公司在英国开展业务充满变数
  6. ROS学习笔记-多机器人通信(1)-实现两台机器通信
  7. 使用 MoveIt 控制自己的真实机械臂【4】——了解 MoveIt 的轨迹规划实现机制
  8. 工作了这么长时间,是不是非用macbook pro不可呢?
  9. 亚商投顾早餐FM/0905北交所首只指数、两融制度要来了
  10. Mesa Overview