第五章---面向对象---1.继承/2.派生/3.继承的实现原理/4.在子类中重用父类的方法和属性

1.继承:指的是类与类之间的关系,是一种什么是什么的关系,继承的功能是解决代码的重用问题,继承是一种创建新类的方式
python 中新建的类可以继承一个或多个父类(基类或超类)
新建的类称为派生类或子类

对象之间相似的特征-------类
类之间相似的特征 ---- 父类

 

继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。

 1 class ParentClass1:
 2     pass
 3 
 4 class ParentClass2:
 5     pass
 6 
 7 class SubClass1(ParentClass1):
 8     pass
 9 
10 class SubClass2(ParentClass1,ParentClass2):
11     pass
12 
13 # print(SubClass1.__bases__)
14 # print(SubClass2.__bases__)
15 #
16 # # (<class '__main__.ParentClass1'>,)
17 # # (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
18 
19 
20 class Hero:
21     def __init__(self,name,attack,life_value):
22         self.name = name
23         self.attack = attack
24         self.life_value = life_value
25 
26     def attack_other(self,enemy):
27         enemy.life_value -= self.attack
28         if enemy.life_value <= 0:
29             print('%s 没有血量,宣布死亡!'% enemy.name)
30         else:
31             print('%s血量剩余%s'% (enemy.name,enemy.life_value))
32 class HeroDog(Hero):
33     pass
34 
35 class HeroPig(Hero):
36     pass
37 
38 hero_d = HeroDog('Dog',10,100)
39 hero_p = HeroPig('pig',20,100)
40 
41 # hero_d.attack_other(hero_p)
42 
43 继承属性查找小练习:
44 
45 练习一:
46 class Foo:
47     def f1(self):
48         print('from Foo.f1')
49     def f2(self):
50         print('from Foo.f2')
51         self.f1()
52 
53 class Bar(Foo):
54     def f2(self):
55         print('from Bar.f2')
56 
57 b1 = Bar()
58 b1.f2()
59 # from Bar.f2
60 b1首先在自己这个对象中找f2(),找不到然后去自己所在的类Bar中去找,找到了输出结果
61 
62 练习二:
63 class Foo:
64     def f1(self):
65         print('from Foo.f1')
66     def f2(self):
67         print('from Foo.f2')
68         self.f1() # b.f1()
69 
70 class Bar(Foo):
71     def f1(self):
72         print('from Bar.f1')
73 
74 b1 = Bar()
75 b1.f2()
76 # from Foo.f2
77 # from Bar.f1
78 # b1首先在自己这个对象中找f2(),找不到然后去自己所在的类Bar中去找,
79 # 仍然找不到就会去Bar的父类Foo中去找,找到了,首先打印的是'from Foo.f2',
80 # 然后会执行self.f1(),由于这个self就是对象b1,所以会继续前面的寻找方式,
81 # 先去自己本身的对象中找,找不到去所在的类,找不到在去类所在的父类!

2.派生
:子类可以添加自己的 新属性 数据属性 函数属性
查找顺序:1.对象本身--》2.对象所在的类里面找--》3.父类里面找
 1 class Hero:
 2     def __init__(self,name,attack,life_value):
 3         self.name = name
 4         self.attack = attack
 5         self.life_value = life_value
 6 
 7     def attack_other(self,enemy):
 8         enemy.life_value -= self.attack
 9         if enemy.life_value <= 0:
10             print('%s 没有血量,宣布死亡!'% enemy.name)
11         else:
12             print('%s血量剩余%s'% (enemy.name,enemy.life_value))
13 
14 class HeroDog(Hero):
15     camp = 'Dog_camp'
16     def attack_other(self,enemy):
17         print('from HeroDog class')
18 
19 class HeroPig(Hero):
20     camp = 'Pig_camp'
21 
22 hero_d = HeroDog('Dog',10,100)
23 hero_p = HeroPig('pig',20,100)
24 hero_d.attack_other(hero_p)

 

3.继承的实现原理:python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表

例如:
>> F.mro() #等同于F.__mro__
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
0.对象本身优先于子类
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类

在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如果继承了多个父类,那么属性的查找方式有两种,
分别是:深度优先和广度优先 (本质按列表顺序来) --》只是一种排序的不同方式

python中类分为两种:1.新式类 2.经典类 (py2中)
1.新式类 (py3 --> 只有新式类)

 

 

 1 # 在python2中-》 经典类:没有继承object的类,以及他的子类都称之为经典类
 2 # class Foo:
 3 #     pass
 4 #
 5 # class Bar(Foo):
 6 #     pass
 7 
 8 # 在python2中-》 新式类:继承了object的类,以及他的子类都称之为经典类
 9 # class Foo(object):
10 #     pass
11 #
12 # class Bar(Foo):
13 #     pass
14 
15 # 在python3中-》 新式类:一个类没有继承object类,默认就继承object
16 # class Foo:
17 #     pass
18 # print(Foo.__bases__)
19 
20 
21 # 验证多继承情况下的属性查找  -- # F D B X E C A  新式类 --》 广度优先
22 class A(object):
23     # def test(self):
24     #     print('from A')
25     pass
26 
27 class B(A):
28     # def test(self):
29     #     print('from B')
30     pass
31 
32 class C(A):
33     # def test(self):
34     #     print('from C')
35     pass
36 
37 class D(B):
38     # def test(self):
39     #     print('from D')
40     pass
41 
42 class E(C):
43     # def test(self):
44     #     print('from E')
45     pass
46 
47 class F(D,E):
48     # def test(self):
49     #     print('from F')
50     pass
51 f1=F()
52 f1.test()
53 print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
54 # (<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
55 
56 #新式类继承顺序:F->D->B->E->C->A
57 #经典类继承顺序:F->D->B->A->E->C
58 #python3中统一都是新式类
59 #pyhon2中才分新式类与经典类

 

 4.在子类中重用父类的方法和属性

在子类派生出的新的方法中重用父类的方法:有两种实现方式:
方式一:指名道姓(不依赖继承)
Hero.attack_other(self,enemy) # 指名道姓 不依赖继承
Hero.__init__(self,name,attack,life_value) # 指名道姓 不依赖继承

方式二:super() (依赖继承) super() 会从对象的(MRO)列表中找
super(Garen,self).attack_other(enemy) # 依赖继承
super(Garen,self).__init__(name,attack,life_value) # 依赖继承 py2 写法
super().__init__(name,attack,life_value) # py3 写法
  1 # 方式一:指名道姓
  2 # class Hero:
  3 #     def __init__(self,name,attack,life_value):
  4 #         self.name = name
  5 #         self.attack = attack
  6 #         self.life_value = life_value
  7 #
  8 #     def attack_other(self,enemy):
  9 #         enemy.life_value -= self.attack
 10 #         if enemy.life_value <= 0:
 11 #             print('%s 没有血量,宣布死亡!'% enemy.name)
 12 #         else:
 13 #             print('%s血量剩余%s'% (enemy.name,enemy.life_value))
 14 #
 15 # class HeroDog(Hero):
 16 #     camp = 'Dog_camp'
 17 #     def attack_other(self,enemy):
 18 #         Hero.attack_other(self,enemy) # 指名道姓方法,不依赖继承
 19 #         print('from HeroDog class')
 20 #
 21 # class HeroPig(Hero):
 22 #     camp = 'Pig_camp'
 23 #
 24 # hero_d = HeroDog('Dog',10,100)
 25 # hero_p = HeroPig('pig',20,100)
 26 # hero_d.attack_other(hero_p)
 27 
 28 
 29 # 方式一:指名道姓
 30 # class Hero:
 31 #     def __init__(self, name, attack, life_value):
 32 #         self.name = name
 33 #         self.attack = attack
 34 #         self.life_value = life_value
 35 #
 36 #     def attack_other(self, enemy):
 37 #         enemy.life_value -= self.attack
 38 #         if enemy.life_value <= 0:
 39 #             print('%s 没有血量,宣布死亡!' % enemy.name)
 40 #         else:
 41 #             print('%s血量剩余%s' % (enemy.name, enemy.life_value))
 42 #
 43 #
 44 # class HeroDog(Hero):
 45 #     camp = 'Dog_camp'
 46 #
 47 #     def __init__(self,name,attack,life_value,weapon):
 48 #         # self.name = name
 49 #         # self.attack = attack
 50 #         # self.life_value = life_value
 51 #         Hero.__init__(self,name,attack,life_value) # 指名道姓方法
 52 #
 53 #         self.weapon = weapon
 54 #
 55 #     def attack_other(self, enemy):
 56 #         Hero.attack_other(self, enemy)  # 指名道姓方法,不依赖继承
 57 #         print('from HeroDog class')
 58 #
 59 # hero_d = HeroDog('Dog', 10, 100,'大刀')
 60 # print(hero_d.__dict__)
 61 
 62 
 63 # 方式二:super() (依赖继承)
 64 # class Hero:
 65 #     def __init__(self,name,attack,life_value):
 66 #         self.name = name
 67 #         self.attack = attack
 68 #         self.life_value = life_value
 69 #
 70 #     def attack_other(self,enemy):
 71 #         enemy.life_value -= self.attack
 72 #         if enemy.life_value <= 0:
 73 #             print('%s 没有血量,宣布死亡!'% enemy.name)
 74 #         else:
 75 #             print('%s血量剩余%s'% (enemy.name,enemy.life_value))
 76 #
 77 # class HeroDog(Hero):
 78 #     camp = 'Dog_camp'
 79 #     def attack_other(self,enemy):
 80 #         super(HeroDog,self).attack_other(enemy) # 依赖继承
 81 #         # super(HeroDog,self) 这就是父类的对象
 82 #         print('from HeroDog class')
 83 #
 84 # class HeroPig(Hero):
 85 #     camp = 'Pig_camp'
 86 #
 87 # hero_d = HeroDog('Dog',10,100)
 88 # hero_p = HeroPig('pig',20,100)
 89 # hero_d.attack_other(hero_p)
 90 
 91 
 92 # 方式二:super() (依赖继承)
 93 # class Hero:
 94 #     def __init__(self, name, attack, life_value):
 95 #         self.name = name
 96 #         self.attack = attack
 97 #         self.life_value = life_value
 98 #
 99 #     def attack_other(self, enemy):
100 #         enemy.life_value -= self.attack
101 #         if enemy.life_value <= 0:
102 #             print('%s 没有血量,宣布死亡!' % enemy.name)
103 #         else:
104 #             print('%s血量剩余%s' % (enemy.name, enemy.life_value))
105 #
106 #
107 # class HeroDog(Hero):
108 #     camp = 'Dog_camp'
109 #
110 #     def __init__(self,name,attack,life_value,weapon):
111 #         # super(HeroDog,self).__init__(name,attack,life_value)
112 #         super().__init__(name, attack, life_value) # python可以这样简写
113 #         self.weapon = weapon
114 #
115 #     def attack_other(self, enemy):
116 #         Hero.attack_other(self, enemy)  # 指名道姓方法,不依赖继承
117 #         print('from HeroDog class')
118 #
119 # hero_d = HeroDog('Dog', 10, 100,'大刀')
120 # print(hero_d.__dict__)
121 
122 #--------------------------------------------------------
123 # A没有继承B,但是A内super会基于C.mro()继续往后找
124 class A:
125     def f1(self):
126         print('from A')
127         super().f1()
128 
129 class B:
130     def f1(self):
131         print('from B')
132 
133 class C(A,B):
134     pass
135 # print(C.mro())
136 # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
137 
138 c = C()
139 c.f1()
140 # from A
141 # from B

 

posted @ 2018-04-26 13:57  mumupa0824  阅读(219)  评论(0编辑  收藏  举报