面向对象的继承

不用继承创建对象

  1. class Person:
  2. def __init__(self,name,sex,age):
  3. self.name = name
  4. self.age = age
  5. self.sex = sex
  6. class Cat:
  7. def __init__(self,name,sex,age):
  8. self.name = name
  9. self.age = age
  10. self.sex = sex
  11. class Dog:
  12. def __init__(self,name,sex,age):
  13. self.name = name
  14. self.age = age
  15. self.sex = sex

Python
Copy
使用继承的方式

  1. class Aniaml(object):
  2. def __init__(self,name,sex,age):
  3. self.name = name
  4. self.age = age
  5. self.sex = sex
  6. class Person(Aniaml):
  7. pass
  8. class Cat(Aniaml):
  9. pass
  10. class Dog(Aniaml):
  11. pass

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

  1. 增加了类的耦合性(耦合性不宜多,宜精)。
  2. 减少了重复代码。
  3. 使得代码更加规范化,合理化。

继承的分类

上面的那个例子:

  • Aminal 叫做父类, 基类, 超类。
  • Person Cat Dog: 子类,派生类。

继承:可以分 单继承,多继承
这里需要补充一下 python 中类的种类(继承需要):
在 python2x 版本中存在两种类.:

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

单继承

类名,对象执行父类方法

  1. class Aniaml(object):
  2. type_name = '动物类'
  3. def __init__(self,name,sex,age):
  4. self.name = name
  5. self.age = age
  6. self.sex = sex
  7. def eat(self):
  8. print('吃',self)
  9. class Person(Aniaml):
  10. pass
  11. class Cat(Aniaml):
  12. pass
  13. class Dog(Aniaml):
  14. pass
  15. print(Person.type_name)
  16. Person.eat('东西')
  17. print(Person.type_name)
  18. p1 = Person('aaron','男',18)
  19. print(p1.__dict__)
  20. print(p1.type_name)
  21. p1.type_name = '666'
  22. print(p1)
  23. p1.eat()

Python
Copy

执行顺序

  1. class Aniaml(object):
  2. type_name = '动物类'
  3. def __init__(self,name,sex,age):
  4. self.name = name
  5. self.age = age
  6. self.sex = sex
  7. def eat(self):
  8. print('吃',self)
  9. class Person(Aniaml):
  10. def eat(self):
  11. print('%s 用筷子吃饭'%self.name)
  12. class Cat(Aniaml):
  13. pass
  14. class Dog(Aniaml):
  15. pass
  16. p1 = Person('eagle','男',18)
  17. p1.eat()

Python
Copy

同时执行类以及父类方法

方法一:如果想执行父类的 func 方法,这个方法并且子类中夜用,那么就在子类的方法中写上:父类.func(对象, 其他参数)

  1. class Aniaml(object):
  2. type_name = '动物类'
  3. def __init__(self,name,sex,age):
  4. self.name = name
  5. self.age = age
  6. self.sex = sex
  7. def eat(self):
  8. print('吃东西')
  9. class Person(Aniaml):
  10. def __init__(self,name,sex,age,mind):
  11. Aniaml.__init__(self,name,sex,age)
  12. self.mind = mind
  13. def eat(self):
  14. Aniaml.eat(111)
  15. print('%s 吃饭'%self.name)
  16. class Cat(Aniaml):
  17. pass
  18. class Dog(Aniaml):
  19. pass
  20. p1 = Person('aaron','男',18,'想吃东西')
  21. p1.eat()

Python
Copy
方法二:利用 super,super().func( 参数)

  1. class Aniaml(object):
  2. type_name = '动物类'
  3. def __init__(self,name,sex,age):
  4. self.name = name
  5. self.age = age
  6. self.sex = sex
  7. def eat(self):
  8. print('吃东西')
  9. class Person(Aniaml):
  10. def __init__(self,name,sex,age,mind):
  11. # super(Person,self).__init__(name,sex,age)
  12. super().__init__(name,sex,age)
  13. self.mind = mind
  14. def eat(self):
  15. super().eat()
  16. print('%s 吃饭'%self.name)
  17. class Cat(Aniaml):
  18. pass
  19. class Dog(Aniaml):
  20. pass
  21. p1 = Person('aaron','男',18,'想吃东西')
  22. p1.eat()

Python
Copy
单继承练习题

  1. class Base:
  2. def __init__(self,num):
  3. self.num = num
  4. def func1(self):
  5. print(self.num)
  6. class Foo(Base):
  7. pass
  8. obj = Foo(123)
  9. obj.func1()
  10. # 运⾏的是Base中的func1

Python
Copy

  1. class Base:
  2. def __init__(self,num):
  3. self.num = num
  4. def func1(self):
  5. print(self.num)
  6. class Foo(Base):
  7. def func1(self):
  8. print("Foo.func1",self.num)
  9. obj = Foo(123)
  10. obj.func1()
  11. # 运⾏的是Foo中的func1

Python
Copy

  1. class Base:
  2. def __init__(self, num):
  3. self.num = num
  4. def func1(self):
  5. print(self.num)
  6. self.func2()
  7. def func2(self):
  8. print("Base.func2")
  9. class Foo(Base):
  10. def func2(self):
  11. print("Foo.func2")
  12. obj = Foo(123)
  13. obj.func1()
  14. # func1是Base中的 func2是⼦类中的

Python
Copy

  1. class Base:
  2. def __init__(self, num):
  3. self.num = num
  4. def func1(self):
  5. print(self.num)
  6. self.func2()
  7. def func2(self):
  8. print(111, self.num)
  9. class Foo(Base):
  10. def func2(self):
  11. print(222, self.num)
  12. lst = [Base(1), Base(2), Foo(3)]
  13. for obj in lst:
  14. obj.func2()

Python
Copy

  1. class Base:
  2. def __init__(self, num):
  3. self.num = num
  4. def func1(self):
  5. print(self.num)
  6. self.func2()
  7. def func2(self):
  8. print(111, self.num)
  9. class Foo(Base):
  10. def func2(self):
  11. print(222, self.num)
  12. lst = [Base(1), Base(2), Foo(3)]
  13. for obj in lst:
  14. obj.func1()

Python
Copy

多继承

  1. class ShenXian: # 神仙
  2. def fei(self):
  3. print("神仙都会⻜")
  4. class Monkey: # 猴
  5. def chitao(self):
  6. print("猴⼦喜欢吃桃⼦")
  7. class SunWukong(ShenXian, Monkey): # 孙悟空是神仙, 同时也是⼀只猴
  8. pass
  9. sxz = SunWukong() # 孙悟空
  10. sxz.chitao() # 会吃桃⼦
  11. sxz.fei() # 会⻜

Python
Copy

经典类的多继承

  1. class A:
  2. pass
  3. class B(A):
  4. pass
  5. class C(A):
  6. pass
  7. class D(B, C):
  8. pass
  9. class E:
  10. pass
  11. class F(D, E):
  12. pass
  13. class G(F, D):
  14. pass
  15. class H:
  16. pass
  17. class Foo(H, G):
  18. pass

Python
Copy
画图
python面向对象:继承 - 图1
在经典类中采⽤的是深度优先,遍历⽅案. 什么是深度优先. 就是⼀条路走到头. 然后再回来. 继续找下⼀个.
类的 MRO(method resolution order): Foo-> H -> G -> F -> E -> D -> B -> A -> C.

新式类的多继承

mro 序列

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

  1. mro(Child(Base1Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )(其中Child继承自Base1, Base2

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

  1. mro( B ) = mro( B(A) )
  2. = [B] + merge( mro(A) + [A] )
  3. = [B] + merge( [A] + [A] )
  4. = [B,A]

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

  1. mro(B) = mro( B(A1, A2, A3 …) )
  2. = [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] )
  3. = ...

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

表头和表尾

表头:列表的第一个元素
表尾:列表中表头以外的元素集合(可以为空)
示例:列表:[A, B, C] 表头是 A,表尾是 B 和 C

列表之间的 + 操作

[A] + [B] = [A, B]
merge 操作示例:
如计算 merge([E,O], [C,E,F,O], [C] )
有三个列表 : ① ② ③

  1. 1 merge不为空,取出第一个列表列表①的表头E,进行判断
  2. 各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表
  3. 2 取出列表②的表头C,进行判断
  4. C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除
  5. merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )
  6. 3 进行下一次新的merge操作 ......
  7. ---------------------

python面向对象:继承 - 图2
计算 mro(A) 方式:

  1. mro(A) = mro( A(B,C) )
  2. 原式= [A] + merge( mro(B),mro(C),[B,C] )
  3. mro(B) = mro( B(D,E) )
  4. = [B] + merge( mro(D), mro(E), [D,E] ) # 多继承
  5. = [B] + merge( [D,O] , [E,O] , [D,E] ) # 单继承mro(D(O))=[D,O]
  6. = [B,D] + merge( [O] , [E,O] , [E] ) # 拿出并删除D
  7. = [B,D,E] + merge([O] , [O])
  8. = [B,D,E,O]
  9. mro(C) = mro( C(E,F) )
  10. = [C] + merge( mro(E), mro(F), [E,F] )
  11. = [C] + merge( [E,O] , [F,O] , [E,F] )
  12. = [C,E] + merge( [O] , [F,O] , [F] ) # 跳过O,拿出并删除
  13. = [C,E,F] + merge([O] , [O])
  14. = [C,E,F,O]
  15. 原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])
  16. = [A,B] + merge( [D,E,O], [C,E,F,O], [C])
  17. = [A,B,D] + merge( [E,O], [C,E,F,O], [C]) # 跳过E
  18. = [A,B,D,C] + merge([E,O], [E,F,O])
  19. = [A,B,D,C,E] + merge([O], [F,O]) # 跳过O
  20. = [A,B,D,C,E,F] + merge([O], [O])
  21. = [A,B,D,C,E,F,O]

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