super().__init__(*args, **kwargs) 做啥?

Posted

技术标签:

【中文标题】super().__init__(*args, **kwargs) 做啥?【英文标题】:What does super().__init__(*args, **kwargs) do?super().__init__(*args, **kwargs) 做什么? 【发布时间】:2021-11-26 05:57:06 【问题描述】:

我不知道super().__init__(*args, **kwargs)在这里做什么。

class B(type):
    def __init__(self, *args, **kwargs):
        self.a = 'a'
        super().__init__(*args, **kwargs)


class A(metaclass=B):
    pass

据我所知,super() 返回一个跟踪 MRO 中当前位置的超类的实例。当调用 super 实例的方法时,super 会查找 MRO 中的下一个类并调用该类的方法。

B.__mro__
(<class '__main__.B'>, <class 'type'>, <class 'object'>)

super().__init__(*args, **kwargs)调用__init__方法,是什么意思?

如果我删除它

class B(type):
    def __init__(self, *args, **kwargs):
        self.a = 'a'


class A(metaclass=B):
    pass

初始化A

x=A()
x.a
'a'

实例x属于A类仍然拥有a的属性,效果相同。

【问题讨论】:

它只是将任何位置和关键字参数传递给父级的“构造函数”。 在不将位置和关键字参数传递给父级的“构造函数”的情况下,效果相同。 它将这些参数传递给它的父构造函数,以便在它的构造中做任何需要做的事情,对于这个特定的例子来说,放置那条线或者不改变任何东西,但它可能需要更多精心设计的继承方案 请举个具体的例子。 【参考方案1】:

这是一个简单的示例

>>> class A:
        def __init__(self, a="a",*argv,**karg):
            super().__init__(*argv,**karg)
            self.a=a

    
>>> class B(A):
        def __init__(self, b="b",*argv,**kargv):
            super().__init__(*argv,**kargv)
            self.b=b

        
>>> class Bad(B):
        def __init__(self,b="bad",*arg,**kargv):
            self.b=b

        
>>> b=B()
>>> b.a
'a'
>>> b.b
'b'
>>> bad=Bad()
>>> bad.b
'bad'
>>> bad.a
Traceback (most recent call last):
  File "<pyshell#220>", line 1, in <module>
    bad.a
AttributeError: 'Bad' object has no attribute 'a'
>>> 

这里A 是我们的基类,我们希望它的任何子类都具有 A 的所有功能以及子类所具有的任何额外功能,然后要添加新功能,我们只需将其子类化并使用 super 委托给我们的父类A知道怎么做,所以我们不重复那些部分,这里B是一个坚持这个原则的子类。

现在Bad 是一个不遵守此原则的子类,因此不会在A 父级的构造中设置任何功能,因此它不会设置其.a 属性,因为它通过不通过 super 调用其父构造函数来拒绝合作。

一些相关的解释视频: Raymond Hettinger - Super considered super! - PyCon 2015

【讨论】:

以上是关于super().__init__(*args, **kwargs) 做啥?的主要内容,如果未能解决你的问题,请参考以下文章

1111

metaclass

深入解析类对象与类实例的创建过程

django浅谈 过滤字段内容

推荐使用的派生方法:super().__init__()

python中super().__init__和类名.__init__的区别