小白跟着大神学Python——Day 19-20 类与类之间的关系,继承
类与类之间的关系:
1.依赖关系
依赖关系就是假如有两个类,有一个类必须是随着另外一个类产生的作用的,类与类耦合性最低。简单的说,比如武器类,他必须是装备给使用者(如人类)才能产生效果,否则他就是只能摆在那里。
class Elephant: def __init__(self, name): self.name = name def open(self, obj): print('%s心里默念1,2,3,开门!' % self.name) obj.open_door() def close(self, obj): print('%s心里默念3,2,1,关门!' % self.name) obj.close_door() class Refrigerator: def __init__(self, name): self.name = name def open_door(self): print('冰箱门被打开了!') def close_door(self): print('冰箱门被关闭了!') e1 = Elephant('神奇的大象') media = Refrigerator('美的') e1.open(media) e1.close(media)
2.关联关系、聚合关系、组合关系
其实关联关系、聚合关系以及组合关系三者,他们主要都是类与类之间产生了联系,他们的区别很难定义,简单通过例子说明一下。
class Boy: def __init__(self, name, girlfriend=None): self.name = name self.girlfriend = girlfriend def have_a_dinner(self): if self.girlfriend: print('%s 和 %s 一起共度晚餐'%(self.name,self.girlfriend.name)) else: print('单身狗吃什么吃') def append_girl(self,girl): self.girlfriend = girl def remove_girl(self): self.girlfriend = None class Girl: def __init__(self, name): self.name = name # 起初创业没有女朋友 b = Boy('大郎') b.have_a_dinner() # 突然有一天 alex 家 拆迁,有女朋友了 g = Girl('如花') b.append_girl(g) b.have_a_dinner() 原本 大郎 和 如花是没有关联的,通过b.append_girl(g)建立起了联系
# 聚合关联 # 老师一定要关联学校 class School: def __init__(self,name,address): self.name = name self.address = address class Teacher: def __init__(self, name,comment,school): self.name = name self.comment = comment self.school = school def check_address(self): print('%s 在%s 办公'%(self.name,self.school.address)) beijing = School('老男孩北京校区','美丽富饶的沙河') shanghai = School('老男孩上海校区','上海漳江新区') shenzhen = School('老男孩深圳校区','南山区平山村儿') # t1 = Teacher('太白','优秀',beijing) t2 = Teacher('海峰','优秀',shanghai) t3 = Teacher('日天','看吧',shenzhen) t1.check_address() # 学校同时也要关乎多个老师(聚合) class School: def __init__(self,name,address): self.name = name self.address = address self.teacher_list = [] def append_teacher(self,teacher): self.teacher_list.append(teacher) class Teacher: def __init__(self, name,comment,school): self.name = name self.comment = comment self.school = school def check_address(self): print('%s 在%s 办公'%(self.name,self.school.address)) beijing = School('老男孩北京校区','美丽富饶的沙河') shanghai = School('老男孩上海校区','上海漳江新区') shenzhen = School('老男孩深圳校区','南山区平山村儿') t1 = Teacher('太白','优秀',beijing) t2 = Teacher('景女神','优秀',beijing) t3 = Teacher('文周','优秀',beijing) # t1.check_address() beijing.append_teacher(t1) beijing.append_teacher(t2) beijing.append_teacher(t3) for i in beijing.teacher_list: print(i.name)
class Gamerole: def __init__(self,name,ad,hp): self.name = name self.ad = ad self.hp = hp def attack(self,p1): p1.hp -= self.ad print('%s攻击%s,%s掉了%s血,还剩%s血'%(self.name,p1.name,p1.name,self.ad,p1.hp)) def equip_weapon(self,wea): self.wea = wea # 组合:给一个对象封装一个属性改属性是另一个类的对象 class Weapon: def __init__(self,name,ad): self.name = name self.ad = ad def weapon_attack(self,p1,p2): p2.hp = p2.hp - self.ad - p1.ad print('%s 利用 %s 攻击了%s,%s还剩%s血' %(p1.name,self.name,p2.name,p2.name,p2.hp)) barry = Gamerole('太白',10,200) panky = Gamerole('金莲',20,50) pillow = Weapon('绣花枕头',2) barry.weapon_attack print(barry.__dict__) barry.equip_wea(666) print(barry.wea) print(barry.__dict__) # 给人物装备武器 barry.equip_weapon(pillow) print(barry.__dict__) barry.wea.weapon_attack(barry,panky)
他们的好处:
1. 代码更合理。
2. 类与类之间的耦合性增强。(但不能太强)
Python的三大特征之一:继承(重点)
1.什么是继承?
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。
子类可以执行类中的属性和方法。
python中类的继承分为:单继承和多继承
python中的类:
经典类:只存在python2x,不继承object的类。所有python2既有经典类,又有新式类
新式类:继承object类,python3所有的类默认都继承object
单继承的时候新式类和经典类调用顺序都一样子类到父类到父父类。
多继承的时候不一样:经典类:深度优先。新式类:mro 继承顺序,C3算法。
2.单继承
单继承其实就是只能由一个老爸,不能认干爹。 class A: def __init__(self,name): self.name = name class B(A): pass class C(B): pass obj =C('n') obj.name # n
# class A: # def __init__(self): # self.func1() # # def func1(self): # print('in A func1') # # class B(A): # def func1(self): # print('in B func1') # # obj = B() # obj.func1() 答案:2个 in B func1
3.多继承
class Immortal: def __init__(self): self.age = '长生不老' def fly(self): print('神仙都会飞') def eat(self): print('神仙也需要进食') class Monkey: def climb(self): print('猴子都会爬树') def eat(self): print('猴子需要进食') class Monkey_sun(Immortal,Monkey): pass sun = Monkey_sun() sun.fly() sun.climb() sun.eat()
经典类多继承查找顺序:
遵循深度优先原则。下图的顺序应是深度优先,从左到右。 Foo-> H -> G -> F -> E -> D -> B -> A -> C. 你猜对了么?

新式类多继承查找顺序:
遵循C3算法。
表头:
列表的第一个元素
表尾:
列表中表头以外的元素集合(可以为空)
示例
列表:[A, B, C]
表头是A,表尾是B和C
通用公式:
mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
(其中Child继承自Base1, Base2)
merge操作示范 如计算merge( [E,O], [C,E,F,O], [C] ) 有三个列表 : ① ② ③ merge不为空,取出第一个列表列表①的表头E,进行判断 各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表 取出列表②的表头C,进行判断 C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除 merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] ) 进行下一次新的merge操作 ...... ---------------------

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] ---------------------
这样的例子,你学会了?面试题可能会考唷!
当然,在工作中不需要你会计算,使用(对象名.__mro__)方法即可查看其继承顺序。
继承的好处: 1. 类与类之间的耦合性增强。 2. 节省代码。 3. 代码更加规范化,合理性。
浙公网安备 33010602011771号