[00807]调用父类方法

调用父类方法

一、 解决问题

在子类中调用父类的某个已经被覆盖的方法。

二、解决方案

super()

三、代码说明

#!/usr/bin/env python

class A:

    def __init__(self):
        self.x = 0

    def spam(self):
        print ("A.spam")

class B(A):

    def __init__(self):
        super().__init__() #调用父类的构造器(不需要手动的传入self)
        self.y = 1

    def spam(self):
        print ("B.spam")
        super().spam()  # call parent spam()


b = B()
b.spam()
print (b.x)
"""
覆盖特殊的方法
"""
class Proxy:
    def __init__(self, obj):
        self._obj = obj

    def __getter__(self, name):
        return getattr(self._obj, name)

    def __setattr__(self, name, value):
        if name.startswith("_"):
            super().__setattr__(name, value) # call original __setattr__
        else:
            setattr(self._obj, name, value)

p = Proxy({"a": 1, "b": 2})
print (getattr(p, "_obj")["a"])
setattr(p, "_obj", [1, 2])
print (dir(p)) 
"""
针对每一个定义的类,Python 都会计算出一个称为方法解析顺序(MRO)d的列表。
MRO只是简单地对所有基类进行线性排序。
"""

"""
要实现继承,Python从MRO列表中最左边的类开始,从左到有依次查询,直到找到带查询的属性为止


当使用super() 函数时,Python会继续从MRO中的下一个类开始搜索,
只要每一个重新定义过的方法(覆盖)都使用super(),并且只调用了它一次,
那么控制流最终就可以遍历整个MRO列表,并且让每个方法都只被执行一次。

super(), 它并不是一定要关联到某一个类的直接父类上,
甚至可以在没有直接父类中使用它。
"""
class A:
    def spam(self):
        print ("A.spam")
        super().spam()  # 寻找mro上一层的spam()方法

#a = A() 
#a.spam()# 'super' object has no attribute 'spam'

class B:
    def spam(self):
        print ("B.spam")

class C(A, B):
    pass

c = C()
c.spam()
"""
A.spam  
B.spam
"""
print (C.__mro__)
##->(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)

四、关联知识

super()函数传送门,待补充

五、总结

  • 首先确保继承体系中所有同名的方法都有可兼容的调用名称(参数类型,个数都相同)如果super() 尝试去调用非直接父类的方法,那么这就可以确保不会遇到麻烦;
  • 其次确保最顶层的类实现了这个方法通常是一个好主意。沿着MRO列表展开的查询链会因为最终找到了实际的方法为止。

六、代码地址

github地址:https://github.com/weichen666/python_cookbooka>
目录/文件:eight_selection/learn_class_obj_super.py

七、参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值