小白跟着大神学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. 代码更加规范化,合理性。
继承的好处

 

posted on 2019-01-16 20:26  C_Jayson  阅读(115)  评论(0)    收藏  举报

导航