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

使用继承的方式

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

单继承

类名,对象执行父类方法

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()

执行顺序

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(对象,其他参数)

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(参数)

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()

单继承练习题

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
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
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是⼦类中的
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()
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() # 会⻜

经典类的多继承

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


文章作者: AaronXu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 AaronXu !
评论
 上一篇
python面向对象:继承,封装,多态 python面向对象:继承,封装,多态
python面向对象的三大特性:继承,封装,多态。 封装: 把很多数据封装到⼀个对象中. 把固定功能的代码封装到⼀个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想. 具体的情况具体分析. 比如. 你写了⼀个很⽜B的函数. 那这
下一篇 
  目录