# 类的继承

## 面向对象的继承

不用继承创建对象

```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
```

画图

![image-20210725220109579](03.%E7%B1%BB%E7%9A%84%E7%BB%A7%E6%89%BF/image-20210725220109579.png) 

在经典类中采⽤的是深度优先，遍历⽅案. 什么是深度优先. 就是⼀条路走到头. 然后再回来. 继续找下⼀个.

类的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操作 ......
    --------------------- 

![image-20210725220122519](03.%E7%B1%BB%E7%9A%84%E7%BB%A7%E6%89%BF/image-20210725220122519.png) 

计算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呢? 因为笔
试.......你在笔试的时候, 是没有电脑的. 所以这个算法要知道. 并且简单的计算要会. 正式项⽬
开发的时候很少有⼈这么去写代码. 