蟒蛇超级调用子方法(python super calling child methods)

2019-07-31 16:24发布

没有关于使用许多问题super()但他们都不似乎回答我的问题。

当调用super().__init__()从子类,所有的方法调用超构造函数实际上是从子类服用。 考虑下面的类结构:

class A(object):
    def __init__(self):
        print("initializing A")
        self.a()
    def a(self):
        print("A.a()")

class B(A):
    def __init__(self):
        super().__init__()
        # add stuff for B
        self.bnum=3 # required by B.a()        
    def a(self):
        print("B.a(), bnum=%i"%self.bnum)

b=B()

其失败

initializing A
Traceback (most recent call last):
  File "classmagic.py", line 17, in 
    b=B()
  File "classmagic.py", line 11, in __init__
    super().__init__()
  File "classmagic.py", line 5, in __init__
    self.a()
  File "classmagic.py", line 15, in a
    print("B.a(), bnum=%i"%self.bnum)
AttributeError: 'B' object has no attribute 'bnum'

在这里,我打电话在超构造B()初始化一些基本结构(其中一些作为自己的功能被执行a() 但是,如果我重写a()函数为好,此实现调用时使用A ,因为它失败的构造A一无所知B ,并可能使用不同的内部变量。

这可能是也可能不是直观的,但我有什么做的,当我想在所有的方法, A只能够访问那里执行的功能?

Answer 1:

如果你的代码必须调用不能被重写特定的私有方法,使用两个下划线开头的名称:

class A(object):
    def __init__(self):
        print("initializing A")
        self.__a()
    def __a(self):
        print("A.a()")

class B(A):
    def __init__(self):
        super().__init__()
        # add stuff for B
        self.bnum=3 # required by B.a()        
    def __a(self):
        print("B.__a(), bnum=%i"%self.bnum)

Python的“轧液”在类名(加下划线)添加到最小化的子类覆盖它们自己版本的机率这种方法名。

该PEP 8 Python的风格指南是这样说的关于私人名字改编:

如果你的类是为了被继承,你有你不想子类使用,可以考虑用双下划线开头命名它们的属性和没有尾随下划线。 这将调用Python的名字改编算法,其中类的名称错位到属性名称。 这有助于避免属性名称冲突应子无意中包含具有相同名称的属性。

注1:请注意,只有简单的类名在错位的名称中使用,因此,如果一个子类都选了相同的类名和属性名,你仍然可以得到名称冲突。

注2:名称重整可以使某些用途,如调试和__getattr__()不太方便。 然而,名称重整算法是有据可查的,易于手动执行。

注3:不是每个人都喜欢的名字改编。 尝试平衡的必要性,以避免意外的名称冲突与先进的呼叫者的潜在用途。



Answer 2:

而不是调用self.a()你需要使用Aa(self) 。 但是,这不是常见的在特定类的所有方法做, 你应该重新评估是否B应继承A



Answer 3:

考虑这个调用:

class B(A):
    def __init__(self):
        A.__init__(self)

这是发生了什么,当你调用super().__init__() 这,反过来,调用self.a()这当然是的函数a类的B而不是A因为self是类的B 。 正如马亭说,你可以使用双下划线的名称,或者明确地使用类名,否则就不可能调用从超类的覆盖方法。



Answer 4:

如果我们通过的instanciation步骤B

  • 我们称之为super(B,self).__init__ ,那就是, A.__init__
  • 这就要求self.a()也就是Ba()在我们的情况下,
  • 它采用self.bnum

除了bnum尚未定义尚未...所以, AttributeError

对于这种特殊的情况下,它只是足以定义你bnumB.__init__调用之前 super(B,self).__init__

class B(A):
    def __init__(self):
       self.bnum=3
       super(B, self).__init__()

去之前名字改编的黑暗,黑暗的道路,您可能希望只取来组织你的子类的代码的时间:应父母的进行,初始化一些特殊变量,或者父母的,要更换一些默认?



文章来源: python super calling child methods