python super使用

文章讨论了Python中多继承时`__init__`方法的调用规则,强调了使用`super`关键字正确初始化父类的重要性,并揭示了菱型问题(即不同继承顺序导致的值重置问题)。
摘要由CSDN通过智能技术生成
class Base1():
    def __init__(self, name):
        self._name = name
        print("name", self._name)
    
    def my_func(self):
        print(self._name)
        

class Base2():
    def __init__(self, age):
        self._age = age
        print("age",self._age)
        
    
    def my_func(self):
        print(self._age)
        
        
class Son(Base1, Base2):
    
    def __init__(self, name, age):
        # 子类多继承时,super参数时子类时,制有第一个继承基类第一个类Base1被初始化
        super(Son, self).__init__(age)
        
        # 初始化Base2
        super(Son, self).__init__(name)
        

    def my_func(self):
        print("son")
        


c = Son("ls", 20)
c.my_func() 
# output:
# name 20
# name ls
# son


class Son1(Base1, Base2):
    
    def __init__(self, name, age):
        
        # super参数填写父类时,按继承顺序只能Base1可以被初始化
        # super(Base1, self).__init__(name) # ok
        # super(Base2, self).__init__(age) # error

        # 不是顺序初始化,报错
        # super(Base2, self).__init__(name) # error
        # super(Base1, self).__init__(age)  # not reach
        
        # 直接使用基类类名调用__init__(), 正确执行
        Base1.__init__(self, name) 
        Base2.__init__(self, age)
        
        
    def my_func(self):
        print("son")

c1 = Son1("ls", 20)
c1.my_func()
# output:
# name ls
# 20
# son



class Son2(Base1, Base2):
    
    def __init__(self, name, age):
        # 子类多继承时,super无参数时,只有第一个继承基类第一个类Base1被初始化
        super().__init__(name)
        super().__init__(age)
        
        # supper加子类名,效果同上
        # super(Son2,self).__init__(name)
        # super(Son2,self).__init__(age)
        
    def my_func(self):
        print("son")
        
c1 = Son2("ls", 20)
c1.my_func()
# output:
# name ls
# name 20
# son

总结:多继承,使用基类名称调用__init__进行初始化父类
# 菱型问题
class MyBaseClass:
    def __init__(self, value):
        self.value = value

class TimesFive(MyBaseClass):
    def __init__(self, value):
        MyBaseClass.__init__(self, value)
        self.value *= 5

class PlueTwo(MyBaseClass):
    def __init__(self, value):
        MyBaseClass.__init__(self, value)
        self.value +=2
        
        
class Test(TimesFive, PlueTwo):
    def __init__(self, value):
        TimesFive.__init__(self, value)
        PlueTwo.__init__(self, value)
        
test = Test(5)
print(test.value)
# output: 7, 而不是预想的27
# 因为PlueTwo后初始化时,调用MyBaseClass.__init__(self, value)父类
# 初始化有对value重新初始化了为5,所以为7

class TimesFiveCorrect(MyBaseClass):
    def __init__(self, value):
        super(TimesFiveCorrect, self).__init__(value)
        self.value *= 5
class PlusTwoCorrect(MyBaseClass):
    def __init__(self, value):
        super(PlusTwoCorrect, self).__init__(value)
        self.value += 2


class TestSuper(TimesFiveCorrect, PlusTwoCorrect):
    def __init__(self, value):
        super(TestSuper, self).__init__(value)
        

test1 = TestSuper(5)    
print(test1.value) # 35而不是预想的27,因为父类实例化规则
# 是根据MRO标准规则,使用mro函数查看初始化树
from pprint import pprint
pprint(TestSuper.mro())
# output:
# [<class '__main__.TestSuper'>,
#  <class '__main__.TimesFiveCorrect'>,
#  <class '__main__.PlusTwoCorrect'>,
#  <class '__main__.MyBaseClass'>,
#  <class 'object'>]
# TestSuper并没有真正执行,先到根MyBaseClass,再由根到TestSuper
# 所以执行结果是(5+2) * 5 = 35
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值