python之继承中组合用法与菱形继承关系查找法

1.什么是组合

    组合就是一个类的对象具备某一属性,该属性的值是指向另外外一个类的对象

2.为什么用组合

    组合也是用来解决类与类之间代码冗余问题

3.用法

class Course:                       #组合
    def __init__(self, name, period, price):
        self.name = name
        self.period = period
        self.price = price

    def tell_info(self):
        msg = """
         课程名:%s
         课程周期:%s
         课程价钱:%s
        """ % (self.name, self.period, self.price)
        print(msg)


class OldboyPeople:                                     #父类
    school = 'oldboy'

    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex


class OldboyStudent(OldboyPeople):                子类
    def __init__(self, name, age, sex, stu_id):
        OldboyPeople.__init__(self, name, age, sex)
        self.stu_id = stu_id

    def choose_course(self):
        print('%s is choosing course' % self.name)


class OldboyTeacher(OldboyPeople):                     #子类

    def __init__(self, name, age, sex, level):
        OldboyPeople.__init__(self, name, age, sex)
        self.level = level

    def score(self, stu, num):
        stu.score = num
        print('老师[%s]为学生[%s]打分[%s]' % (self.name, stu.name, num))


# 创造课程
python = Course('python全栈开发', '5mons', 3000)
linux = Course('linux运维', '5mons', 800)
# python.tell_info()
# linux.tell_info()


# 创造学生与老师
stu1 = OldboyStudent('猪哥', 19, 'male', 1)
tea1 = OldboyTeacher('egon', 18, 'male', 10)

# 将学生、老师与课程对象关联/组合
stu1.course = python     #把课程python对象内存地址添加到stu1对象名称空间中,之后可以直接调用到course中的函数
print(stu1.__dict__)    
tea1.course = linux

stu1.course.tell_info()      直接用绑定方法调用组合里面的函数属性
tea1.course.tell_info()

二.菱形继承关系查找法

1.菱形继承

    当一个子类继承多个父类时,多个父类最终继承了同一个类,称之为菱形继承

2.菱形继承的问题:

    python2区分经典类与新式类,如果子类继承的是一个菱形继承,那么经典类与新式类的区别是:

    经典类下查找属性为:深度优先查找(先一条道走到底,在找别的父类)

    新式类下查找属性为:广度优先查找(先每条道的找,最后一条道就查找到底)

python2中经典类

python3中新式类

继承原理:

python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如

__mro__查看继承查找

class A(object):
    def test(self):
        print('from A')

class B(A):
    def test(self):
        print('from B')

class C(A):
    def test(self):
        print('from C')

class D(B):
    def test(self):
        print('from D')

class E(C):
    def test(self):
        print('from E')

class F(D,E):
    # def test(self):
    #     print('from F')
    pass
f1=F()
f1.test()
print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性

#新式类继承顺序:F->D->B->E->C->A
#经典类继承顺序:F->D->B->A->E->C
#python3中统一都是新式类
#pyhon2中才分新式类与经典类

继承顺序
>>> F.mro() #等同于F.__mro__
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类

原文地址:https://www.cnblogs.com/Marcki/p/10111944.html