ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python面向对象super()和mro机制

2021-12-06 21:33:41  阅读:148  来源: 互联网

标签:__ python self init mro 父类 super


[moc]

super()和mro列表

super()

#  在python中super一般用在继承中,通过super我们可以调用父类。
# 这段代码中定义了一个子类Son,它继承与父类Father,实例化对象可以调用父类中的__init__方法
class Father():
    def __init__(self):
        print("这是父类的")
        
class Son(Father):
    def __init__(self):
        Father.__init__(self)  # 调用父类的__init__ 类的调用需要传入参数self
        print("这是子类的")

son = Son()

打印出:这是父类的
	   这是子类的
 
'''
通过这样调用父类,我们就实现了既可以调用子类方法,也可以调用父类方法。如果不这样调用的话,当子类继承一个父类的时候,使用__init__方法的话,子类就会覆盖父类,我们就无法访问父类的__init__方法。
'''

! 通过super()实现上述代码

class Father(): # Father为父类
    def __init__(self):
        print("这是父类的")

class Son(Father):  # Father为Son的父类
    def __init__(self):
        super(Son, self).__init__()   # 这里使用super()语句 实现相同的效果 
        super().__init__()  # python3中super()括号内无需传入参数
        print("这是子类的")
        
son = Son() # 类的实例化对象

打印出:这是父类的
	   这是子类的
 
# 当我们使用super方法时,我们需要在super中传入子类的类名和self,无需再__init__方法中传入self 可以看到和上面的结果是一样的

使用super()的好处

## 为什么上边的可以实现 还要使用super()呢  
示例:
class Grandfather(): # Grandfather为父类  #这里修改了原先的父类
    def __init__(self):
        print("这是父类的")

class Son(Grandfather):  # Grandfather为Son的父类
    def __init__(self):
        super(Son, self).__init__() 
        print("这是子类的")
        
son = Son() # 类的实例化对象

这是父类的
这是子类的

'''

这样我们可以看到,当我们修改了Son继承的父类时,代码的结果仍然时相同的,我们不需要修改内部的内名.用第一种方法时有一个不好的地方就是,需要将父类名写到子类中,而我们用super方法就可以解决这个问题。

'''

mro机制

'''
事实上,在每个类声明之后,Python都会自动为创建一个名为“__mro__”的内置属性,这个属性就是Python的MRO机制生成的,该属性是一个tuple,定义的是该类的方法解析顺序(继承顺序),
当用super调用父类的方法时,会按照__mro__属性中的元素顺序去挨个查找方法。我们可以通过“类名.__mro__”或“类名.mro()”来查看代码中类的__mro__属性值

'''
本质上:这个顺序是怎么生成的呢?在Python新式类中(Python3中也只存在新式类了),采用的是C3算法(可不是广度优先,更不是深度优先)。
#A没有继承B,但是A内super会基于C.mro()继续往后找
class A:
    def test(self):
        print('A---->test')
        super().aaa()
class B:
    def test(self):
        print('B---->test')

    def aaa(self):
        print('B---->aaa')

class C(A,B):
    def aaa(self):
        print('C----->aaa')

c=C()
c.test() #打印结果:
'''
A---->test
B---->aaa
'''
print(C.mro())
#打印结果为:
#[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]

# C作为方法调用(即c.test())的发起者,方法调用过程中涉及的属性查找都参考C.mro()。父子关系按照mro列表为准,千万不要从代码层面看父子。例如
# c.test(),发起者C.mro()列表如下,从列表中可以看出,B类就是A类的父类,而代码层面二者并无继承关系
注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表)

标签:__,python,self,init,mro,父类,super
来源: https://www.cnblogs.com/jjjmhf50/p/15651945.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有