情景模式:假设你正在参与一个魔幻类角色游戏的开发,公司需要你为这个游戏设计两个角色的类:
剑士
具有如下属性:
具有如下行为:
法师
具有如下属性:
具有如下行为:
代码实现:
英勇的剑士:
class SwordsMan:
def __init__(self, name, level, blood, attack_power):
'''
:param name:角色姓名
:param level:角色等级
:param blood:角色血量
'''
self.name = name
self.level = level
self.blood = blood
self.power = attack_power
def fight(self): #角色攻击行为
print('物理攻击')
def __str__(self):
return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__,
name = self.name,
level = self.level,
blood = self.blood)
智慧的法师:
class Magician:
def __init__(self, name, level, blood, magic_power):
'''
:param name:角色姓名
:param level:角色等级
:param blood:角色血量
'''
self.name = name
self.level = level
self.blood = blood
self.power = magic_power
def fight(self): #角色攻击行为
print('魔法攻击')
def __str__(self):
return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__,
name = self.name,
level = self.level,
blood = self.blood)
继承 问题引入
问题一: 两个中有大量重复的代码,是否能够只写一次 ?
问题二: 继承的意义是什么 ?
问题三: 继承是复制变量空间嘛 ?
对以上连个角色进行进一步抽象,定义一个更加抽象的类— 角色类
代码如下:
class Rloe:
def __init__(self,name,level,blood):
'''
:param name:角色姓名
:param level:角色等级
:param blood:角色血量
'''
self.name = name
self.level =level
self.blood = blood
def __str__(self):
return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__,
name = self.name,
level = self.level,
blood = self.blood)
def fight(self): # 角色攻击行为
raise NotImplementedError('必须在子类中实现该行为')
继承关系图
再从角色类中派生具体的类
注意:(派生与继承是一个意思的两个说法)
派生出的剑士:
class SwordsMan(Rloe): #继承自Role
def __init__(self,name,level,blood,attack_power):
'''
:param name:角色姓名
:param level:角色等级
:param blood:角色血量
'''
Rloe.__init__(self,name,level,blood)
self.attack_power = attack_power
def fight(self): #角色攻击行为
print('物理攻击')
派生出的法师:
class Magician: #继承自Role
def __init__(self,name,level,blood,magic_power):
'''
:param name:角色姓名
:param level:角色等级
:param blood:角色血量
'''
Rloe.__init__(self, name, level, blood)
self.attack_power = attack_power
def fight(self): #角色攻击行为
print('魔法攻击')
def cure(self): # 角色技能
print('治疗')
搜索原则:(访问类的属性或方法)
实例:
class BaseClass:
attritube = 1
def method(self):
pass
class DeriverClass: #简单继承,没有任何的封装,重写
pass
print(DeriverClass.__dict__) #DeriverClass中没有attritube与method
print(BaseClass.__dict__) #BaseClass中有
重用父类的 _ init_
左边的self 是 剑士(子类)的实例 右边的self是也是剑士的实例
顶级基类 object
class ClassName:
pass
class ClassN(object):
pass
print(ClassName.__bases__)
print(ClassN.__bases__)
思考:为什么返回的是一个元祖 ?
多重继承 问题引入
问题一: 一个类只能有一个基类嘛 ?
问题二: 如果有多个基类,如果有同名属性和方法,应该如何选择?
问题三: 有没有一种更加优雅的方式调用父类的方法 ?
继承关系图:
代码实现如下:
class D:
pass
class E:
pass
class C:
pass
class B(D,E):
pass
class A(B,C):
pass
print(A.mro())
结果输出:
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.E'>, <class '__main__.C'>, <class 'object'>]
进程已结束,退出代码0
MRO-C3 搜索分析
S[D] =
S[E] =
S[C] =
S[B] = B + merge(S[D], S[E], )
= B + merge(, , )
= + merge(O, , E)
=
S[A] = A + merge(S[B], S[C], )
= A + merge(, , )
= + merge(, , C)
= + merge(, , C)
= + merge(O, , C)
=
由于冲突导致的不能继承
代码实现如下:
class A:
pass
class B:
pass
class C(A,B):
pass
class D(B,A):
pass
class E(C,D):
pass
print(E.mro())
结果输出:
Traceback (most recent call last):
File "G:/xxx/xxx/xxx/xxx/TTT.py", line 14, in
class E(C,D):
TypeError: Cannot create a consistent method resolution
order (MRO) for bases A, B
MRO-C3 搜索分析
S[A] =
S[B] =
S[C] = C + merge(S[A], S[B], )
= C + merge(, , )
= + merge(O, , )
=
S[D] =
S[E] = E + merge(S[C], S[D], )
= E + merge(, , )
= + merge(, , )
= + merge(, ) # 冲突
实例:
def draw_fight(role):
print('role',end='')
role.fight() #其实并不关心,role是不是一个实例
class SwordsMan:
def __init__(self, name, level, blood, attack_power):
'''
:param name:角色姓名
:param level:角色等级
:param blood:角色血量
'''
self.name = name
self.level = level
self.blood = blood
self.power = attack_power
def fight(self): #角色攻击行为
print('物理攻击')
def __str__(self):
return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__,
name = self.name,
level = self.level,
blood = self.blood)
class Magician:
def __init__(self, name, level, blood, magic_power):
'''
:param name:角色姓名
:param level:角色等级
:param blood:角色血量
'''
self.name = name
self.level = level
self.blood = blood
self.power = magic_power
def fight(self): #角色攻击行为
print('魔法攻击')
def __str__(self):
return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__,
name = self.name,
level = self.level,
blood = self.blood)
s = SwordsMan('lili',19,3000,150)
m = Magician('haha',18,1000,330)
draw_fight(s) #打印出:role物理攻击
draw_fight(m) #打印出:role魔法攻击
如果走起路来像鸭子,或者叫起来像鸭子,那就是鸭子!
原则:
如何更加优雅的调用父类中方法?
代码实现如下:
剑士super方法改进:
class SwordsMan(Rloe): #继承自Role
def __init__(self,name,level,blood,attack_power):
'''
:param name:角色姓名
:param level:角色等级
:param blood:角色血量
'''
super().__init__(name,level,blood)
self.attack_power = attack_power
def fight(self): #角色攻击行为
print('物理攻击')
法师剑士super方法改进:
class Magician: #继承自Role
def __init__(self,name,level,blood,magic_power):
'''
:param name:角色姓名
:param level:角色等级
:param blood:角色血量
'''
super().__init__(name, level, blood)
self.attack_power = attack_power
def fight(self): #角色攻击行为
print('魔法攻击')
def cure(self): # 角色技能
print('治疗')
super不需要再传self、super是通过mro查找的
练习:
eg:
假设你正在参与潭州教育公司的软件学员管理系统开发,需要你为系统设计学员类:潭州教育软件类别:
请设计一个基类表示学员,然后使用继承来实现各科目的软件学员。
代码实现如下:
class Student:
def __init__(self,name,age,sex):
'''
:param name:学员姓名
:param age:学员年龄
:param sex:学员性别
'''
self.name = name
self.age =age
self.sex = sex
def __str__(self):
return "{clc}({name},{age},{sex})".format(clc = self.__class__.__name__,
name = self.name,
age = self.age,
sex = self.sex)
def learn(self): # 学员学习课程
raise NotImplementedError('必须在子类中实现该方法')
class C(Student): #继承自Student
def __init__(self,name,age,sex,lesson):
'''
:param name:学员姓名
:param age:学员年龄
:param sex:学员性别
'''
super().__init__(name,age,sex)
self.lesson = lesson
def learn(self): #学习课程
print('学习C/C++课程')
class Web(Student): #继承自Student
def __init__(self,name,age,sex,lesson):
'''
:param name:学员姓名
:param age:学员年龄
:param sex:学员性别
'''
super().__init__(name,age,sex)
self.lesson = lesson
def learn(self): #学习课程
print('学习Web前端课程')
class Python(Student): #继承自Student
def __init__(self,name,age,sex,lesson):
'''
:param name:学员姓名
:param age:学员年龄
:param sex:学员性别
'''
super().__init__(name,age,sex)
self.lesson = lesson
def learn(self): #学习课程
print('学习Python课程')
c= C('lili',18,'M','c/c++')
w= Web('haha',19,'F','Web前端')
p= Python('dada',20,'M','Python')
print(c)
c.learn()
print(w)
w.learn()
print(p)
p.learn()
输出结果:
C(lili,18,M)
学习C/C++课程
Web(haha,19,F)
学习Web前端课程
Python(dada,20,M)
学习Python课程
>>>