首页 > 解决方案 > 调用 super().method() 与 BaseClass.method(self)

问题描述

派生类调用基类的方法有两种主要方式。

Base.method(self):

class Derived(Base):
    def method(self):
        Base.method(self)
        ...

super().method():

class Derived(Base):
    def method(self):
        super().method()
        ...

假设我现在这样做:

obj = Derived()
obj.method()

据我所知,两者都Base.method(self)super().method()同样的事情。两者都会Base.method调用obj. 特别是,super()不执行实例化类型对象的繁琐工作Base。相反,它会创建一个类型的新对象super并将实例属性移植到它上面,然后当您尝试从超级对象中获取它时obj,它会动态查找正确的属性。Base

当您更改派生类的基类时,该super()方法的优点是可以最大限度地减少您需要做的工作。另一方面,Base.method当一个类从多个基类继承时,使用更少的魔法并且可能更简单和更清晰。

我看到的大多数讨论都建议调用super(),但这是 Python 编码人员的既定标准吗?还是这两种方法都在实践中广泛使用?例如,这个 stackoverflow 问题的答案是双向的,但通常使用该super()方法。另一方面,我这学期教的Python 教科书Base.method只展示了这种方法。

标签: pythonpython-3.xclassoopinheritance

解决方案


Usingsuper()意味着下面的任何东西都应该委托给基类,不管它是什么。这是关于语句的语义。Base另一方面,明确提及传达了Base出于某种原因(读者可能不知道)明确选择的想法,这也可能有其应用。

然而除此之外还有一个非常实际的使用理由super(),即协作多重继承。假设您设计了以下类层次结构:

class Base:
    def test(self):
        print('Base.test')

class Foo(Base):
    def test(self):
        print('Foo.test')
        Base.test(self)

class Bar(Base):
    def test(self):
        print('Bar.test')
        Base.test(self)

现在您可以同时使用FooBar一切都按预期工作。然而,这两个类不能在多重继承模式中一起工作:

class Test(Foo, Bar):
    pass

Test().test()
# Output:
# Foo.test
# Base.test

最后一次调用testskip overBar的实现,因为Foo没有指定它要按方法解析顺序委托给下一个类,而是明确指定Base。使用super()解决了这个问题:

class Base:
    def test(self):
        print('Base.test')

class Foo(Base):
    def test(self):
        print('Foo.test')
        super().test()

class Bar(Base):
    def test(self):
        print('Bar.test')
        super().test()

class Test(Foo, Bar):
    pass

Test().test()
# Output:
# Foo.test
# Bar.test
# Base.test

推荐阅读