面向对象的继承
不用继承创建对象
class Person:def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sexclass Cat:def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sexclass Dog:def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sex
Python
Copy
使用继承的方式
class Aniaml(object):def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sexclass Person(Aniaml):passclass Cat(Aniaml):passclass Dog(Aniaml):pass
Python
Copy
继承的有点也是显而易见的:
- 增加了类的耦合性(耦合性不宜多,宜精)。
- 减少了重复代码。
- 使得代码更加规范化,合理化。
继承的分类
上面的那个例子:
- Aminal 叫做父类, 基类, 超类。
- Person Cat Dog: 子类,派生类。
继承:可以分 单继承,多继承。
这里需要补充一下 python 中类的种类(继承需要):
在 python2x 版本中存在两种类.:
- ⼀个叫 经典类. 在 python2.2 之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写.
- ⼀个叫 新式类. 在 python2.2 之后出现了新式类. 新式类的特点是基类的根是 object 类。
python3x 版本中只有一种类:
python3 中使⽤的都是 新式类. 如果基类谁都不继承. 那这个类会默认继承 object
单继承
类名,对象执行父类方法
class Aniaml(object):type_name = '动物类'def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sexdef eat(self):print('吃',self)class Person(Aniaml):passclass Cat(Aniaml):passclass Dog(Aniaml):passprint(Person.type_name)Person.eat('东西')print(Person.type_name)p1 = Person('aaron','男',18)print(p1.__dict__)print(p1.type_name)p1.type_name = '666'print(p1)p1.eat()
Python
Copy
执行顺序
class Aniaml(object):type_name = '动物类'def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sexdef eat(self):print('吃',self)class Person(Aniaml):def eat(self):print('%s 用筷子吃饭'%self.name)class Cat(Aniaml):passclass Dog(Aniaml):passp1 = Person('eagle','男',18)p1.eat()
Python
Copy
同时执行类以及父类方法
方法一:如果想执行父类的 func 方法,这个方法并且子类中夜用,那么就在子类的方法中写上:父类.func(对象, 其他参数)
class Aniaml(object):type_name = '动物类'def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sexdef eat(self):print('吃东西')class Person(Aniaml):def __init__(self,name,sex,age,mind):Aniaml.__init__(self,name,sex,age)self.mind = minddef eat(self):Aniaml.eat(111)print('%s 吃饭'%self.name)class Cat(Aniaml):passclass Dog(Aniaml):passp1 = Person('aaron','男',18,'想吃东西')p1.eat()
Python
Copy
方法二:利用 super,super().func( 参数)
class Aniaml(object):type_name = '动物类'def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sexdef eat(self):print('吃东西')class Person(Aniaml):def __init__(self,name,sex,age,mind):# super(Person,self).__init__(name,sex,age)super().__init__(name,sex,age)self.mind = minddef eat(self):super().eat()print('%s 吃饭'%self.name)class Cat(Aniaml):passclass Dog(Aniaml):passp1 = Person('aaron','男',18,'想吃东西')p1.eat()
Python
Copy
单继承练习题
class Base:def __init__(self,num):self.num = numdef func1(self):print(self.num)class Foo(Base):passobj = Foo(123)obj.func1()# 运⾏的是Base中的func1
Python
Copy
class Base:def __init__(self,num):self.num = numdef func1(self):print(self.num)class Foo(Base):def func1(self):print("Foo.func1",self.num)obj = Foo(123)obj.func1()# 运⾏的是Foo中的func1
Python
Copy
class Base:def __init__(self, num):self.num = numdef 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()# func1是Base中的 func2是⼦类中的
Python
Copy
class Base:def __init__(self, num):self.num = numdef 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()
Python
Copy
class Base:def __init__(self, num):self.num = numdef 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()
Python
Copy
多继承
class ShenXian: # 神仙def fei(self):print("神仙都会⻜")class Monkey: # 猴def chitao(self):print("猴⼦喜欢吃桃⼦")class SunWukong(ShenXian, Monkey): # 孙悟空是神仙, 同时也是⼀只猴passsxz = SunWukong() # 孙悟空sxz.chitao() # 会吃桃⼦sxz.fei() # 会⻜
Python
Copy
经典类的多继承
class A:passclass B(A):passclass C(A):passclass D(B, C):passclass E:passclass F(D, E):passclass G(F, D):passclass H:passclass Foo(H, G):pass
Python
Copy
画图
在经典类中采⽤的是深度优先,遍历⽅案. 什么是深度优先. 就是⼀条路走到头. 然后再回来. 继续找下⼀个.
类的 MRO(method resolution order): Foo-> H -> G -> F -> E -> D -> B -> A -> C.
新式类的多继承
mro 序列
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 算法的核心。
表头和表尾
表头:列表的第一个元素
表尾:列表中表头以外的元素集合(可以为空)
示例:列表:[A, B, C] 表头是 A,表尾是 B 和 C
列表之间的 + 操作
[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]
那既然 python 提供了. 为什么我们还要如此⿇烦的计算 MRO 呢? 因为笔
试……. 你在笔试的时候, 是没有电脑的. 所以这个算法要知道. 并且简单的计算要会. 正式项⽬
开发的时候很少有⼈这么去写代码.
