first commit
This commit is contained in:
422
02.面向对象/03.类的继承.md
Normal file
422
02.面向对象/03.类的继承.md
Normal file
@@ -0,0 +1,422 @@
|
||||
# 类的继承
|
||||
|
||||
## 面向对象的继承
|
||||
|
||||
不用继承创建对象
|
||||
|
||||
```python
|
||||
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
|
||||
```
|
||||
|
||||
使用继承的方式
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
## 单继承
|
||||
|
||||
### 类名,对象执行父类方法
|
||||
|
||||
```python
|
||||
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)
|
||||
|
||||
class Person(Aniaml):
|
||||
pass
|
||||
|
||||
class Cat(Aniaml):
|
||||
pass
|
||||
|
||||
class Dog(Aniaml):
|
||||
pass
|
||||
|
||||
print(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
|
||||
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)
|
||||
|
||||
class Person(Aniaml):
|
||||
|
||||
def eat(self):
|
||||
print('%s 用筷子吃饭'%self.name)
|
||||
|
||||
class Cat(Aniaml):
|
||||
pass
|
||||
|
||||
class Dog(Aniaml):
|
||||
pass
|
||||
|
||||
p1 = Person('eagle','男',18)
|
||||
p1.eat()
|
||||
```
|
||||
|
||||
### 同时执行类以及父类方法
|
||||
|
||||
方法一:如果想执行父类的func方法,这个方法并且子类中夜用,那么就在子类的方法中写上:父类.func(对象,其他参数)
|
||||
|
||||
```python
|
||||
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):
|
||||
Aniaml.__init__(self,name,sex,age)
|
||||
self.mind = mind
|
||||
|
||||
def eat(self):
|
||||
Aniaml.eat(111)
|
||||
print('%s 吃饭'%self.name)
|
||||
class Cat(Aniaml):
|
||||
pass
|
||||
|
||||
class Dog(Aniaml):
|
||||
pass
|
||||
|
||||
p1 = Person('aaron','男',18,'想吃东西')
|
||||
p1.eat()
|
||||
```
|
||||
|
||||
方法二:利用super,super().func(参数)
|
||||
|
||||
```python
|
||||
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):
|
||||
# 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('aaron','男',18,'想吃东西')
|
||||
p1.eat()
|
||||
```
|
||||
|
||||
单继承练习题
|
||||
|
||||
```python
|
||||
class Base:
|
||||
def __init__(self,num):
|
||||
self.num = num
|
||||
def func1(self):
|
||||
print(self.num)
|
||||
|
||||
class Foo(Base):
|
||||
pass
|
||||
|
||||
obj = Foo(123)
|
||||
obj.func1()
|
||||
# 运⾏的是Base中的func1
|
||||
```
|
||||
|
||||
```python
|
||||
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
|
||||
```
|
||||
|
||||
```python
|
||||
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()
|
||||
# func1是Base中的 func2是⼦类中的
|
||||
```
|
||||
|
||||
```python
|
||||
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()
|
||||
```
|
||||
|
||||
```python
|
||||
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()
|
||||
```
|
||||
|
||||
## 多继承
|
||||
|
||||
```python
|
||||
class ShenXian: # 神仙
|
||||
def fei(self):
|
||||
print("神仙都会⻜")
|
||||
class Monkey: # 猴
|
||||
def chitao(self):
|
||||
print("猴⼦喜欢吃桃⼦")
|
||||
class SunWukong(ShenXian, Monkey): # 孙悟空是神仙, 同时也是⼀只猴
|
||||
pass
|
||||
|
||||
sxz = SunWukong() # 孙悟空
|
||||
sxz.chitao() # 会吃桃⼦
|
||||
sxz.fei() # 会⻜
|
||||
```
|
||||
|
||||
### 经典类的多继承
|
||||
|
||||
```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(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呢? 因为笔
|
||||
试.......你在笔试的时候, 是没有电脑的. 所以这个算法要知道. 并且简单的计算要会. 正式项⽬
|
||||
开发的时候很少有⼈这么去写代码.
|
Reference in New Issue
Block a user