为什么 Python super 在 child 的 init 方法中使用?
Why is Python super used in the child's init method?
根据Python docs super()
is useful for accessing inherited methods that have been overridden in
a class.
我知道 super 指的是 parent class 并且它允许您访问 parent 方法。我的问题是为什么人们总是在 child class 的 init 方法中使用 super?我到处都见过它。例如:
class Person:
def __init__(self, name):
self.name = name
class Employee(Person):
def __init__(self, **kwargs):
super().__init__(name=kwargs['name']) # Here super is being used
def first_letter(self):
return self.name[0]
e = Employee(name="John")
print(e.first_letter())
我可以在没有 super 甚至没有 init 方法的情况下完成同样的事情:
class Person:
def __init__(self, name):
self.name = name
class Employee(Person):
def first_letter(self):
return self.name[0]
e = Employee(name="John")
print(e.first_letter())
后一种代码有缺点吗?对我来说它看起来干净多了。我什至不必使用样板 **kwargs 和 kwargs['argument'] 语法。
我正在使用 Python 3.8。
编辑:这里有一个 nother Whosebug 个问题,其中包含来自在 child 的 init 方法中使用 super 的不同人的代码。我不明白为什么。我最好的猜测是 Python 3.8.
中有一些新内容
child 可能想要做一些与超级 class 不同的事情,或者更可能是额外的事情 - 在这种情况下,child 必须有一个 __init__
。
调用 super 的 init 意味着您不必 copy/paste(包含维护的所有含义)child 的 class 中的 init,否则将是如果您想在 child init.
中添加一些额外的代码,则需要
但是请注意,如果您使用多重继承(例如调用哪个 super),那么使用 super 的 init 会很复杂,这需要小心。就个人而言,我避免多重继承并将继承保持在最低限度 - 很容易被诱惑创建多个级别的 inheritance/class 层次结构,但我的经验是“保持简单”的方法通常要好得多。
这里使用super
的正确方法是两种方法都使用super
。您不能假设 Person
是 MRO 中的最后一个(或者至少是 object
之前的倒数第二个)class。
class Person:
def __init__(self, name, **kwargs):
super().__init__(**kwargs)
self.name = name
class Employee(Person):
# Optional, since Employee.__init__ does nothing
# except pass the exact same arguments "upstream"
def __init__(self, **kwargs):
super().__init__(**kwargs)
def first_letter(self):
return self.name[0]
考虑一个 class 定义,例如
class Bar:
...
class Foo(Person, Bar):
...
Foo
的 MRO 看起来像 [Foo, Person, Bar, object]
; Person.__init__
中对 super().__init__
的调用将调用 Bar.__init__
,而不是 object.__init__
,并且 Person
无法知道 **kwargs
中的值是否意味着对于 Bar
,因此它 必须 传递它们。
后一种代码的潜在缺点是在 Employee class 中没有 __init__
方法。由于有none,所以调用父class的__init__
方法。但是,一旦将 __init__
方法添加到 Employee class(可能有一些特定于 Employee 的属性需要初始化,例如 id_number),那么 __init__
父 class 的方法被覆盖且未被调用(除非调用 super.__init__()
),然后 Employee 将没有 name
属性。
根据Python docs super()
is useful for accessing inherited methods that have been overridden in a class.
我知道 super 指的是 parent class 并且它允许您访问 parent 方法。我的问题是为什么人们总是在 child class 的 init 方法中使用 super?我到处都见过它。例如:
class Person:
def __init__(self, name):
self.name = name
class Employee(Person):
def __init__(self, **kwargs):
super().__init__(name=kwargs['name']) # Here super is being used
def first_letter(self):
return self.name[0]
e = Employee(name="John")
print(e.first_letter())
我可以在没有 super 甚至没有 init 方法的情况下完成同样的事情:
class Person:
def __init__(self, name):
self.name = name
class Employee(Person):
def first_letter(self):
return self.name[0]
e = Employee(name="John")
print(e.first_letter())
后一种代码有缺点吗?对我来说它看起来干净多了。我什至不必使用样板 **kwargs 和 kwargs['argument'] 语法。
我正在使用 Python 3.8。 编辑:这里有一个 nother Whosebug 个问题,其中包含来自在 child 的 init 方法中使用 super 的不同人的代码。我不明白为什么。我最好的猜测是 Python 3.8.
中有一些新内容child 可能想要做一些与超级 class 不同的事情,或者更可能是额外的事情 - 在这种情况下,child 必须有一个 __init__
。
调用 super 的 init 意味着您不必 copy/paste(包含维护的所有含义)child 的 class 中的 init,否则将是如果您想在 child init.
中添加一些额外的代码,则需要但是请注意,如果您使用多重继承(例如调用哪个 super),那么使用 super 的 init 会很复杂,这需要小心。就个人而言,我避免多重继承并将继承保持在最低限度 - 很容易被诱惑创建多个级别的 inheritance/class 层次结构,但我的经验是“保持简单”的方法通常要好得多。
这里使用super
的正确方法是两种方法都使用super
。您不能假设 Person
是 MRO 中的最后一个(或者至少是 object
之前的倒数第二个)class。
class Person:
def __init__(self, name, **kwargs):
super().__init__(**kwargs)
self.name = name
class Employee(Person):
# Optional, since Employee.__init__ does nothing
# except pass the exact same arguments "upstream"
def __init__(self, **kwargs):
super().__init__(**kwargs)
def first_letter(self):
return self.name[0]
考虑一个 class 定义,例如
class Bar:
...
class Foo(Person, Bar):
...
Foo
的 MRO 看起来像 [Foo, Person, Bar, object]
; Person.__init__
中对 super().__init__
的调用将调用 Bar.__init__
,而不是 object.__init__
,并且 Person
无法知道 **kwargs
中的值是否意味着对于 Bar
,因此它 必须 传递它们。
后一种代码的潜在缺点是在 Employee class 中没有 __init__
方法。由于有none,所以调用父class的__init__
方法。但是,一旦将 __init__
方法添加到 Employee class(可能有一些特定于 Employee 的属性需要初始化,例如 id_number),那么 __init__
父 class 的方法被覆盖且未被调用(除非调用 super.__init__()
),然后 Employee 将没有 name
属性。