Python面向对象:继承

面向对象的继承

不用继承创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

使用继承的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

单继承

类名,对象执行父类方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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()

执行顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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(对象,其他参数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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(参数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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()

单继承练习题

1
2
3
4
5
6
7
8
9
10
11
12
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
1
2
3
4
5
6
7
8
9
10
11
12
13
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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是⼦类中的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()

多继承

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

sxz = SunWukong() # 孙悟空
sxz.chitao() # 会吃桃⼦
sxz.fei() # 会⻜

经典类的多继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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

画图

img

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

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

img

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

评论
加载中,最新评论有1分钟缓存...