Python super() 传入 *args
Python super() pass in *args
我对在 python 继承中的 super().__init__()
中传递 *args
的约定感到困惑。
我理解需要使用关键字参数 **kwargs
以便在需要时 CRO 中的 class 可以获取所需的参数,但为什么还有 *args
?
示例:
假设 Sneaky 被用作多重继承 class 结构的一部分,例如:
class Sneaky:
def __init__(self, sneaky = false, *args, **kwargs):
super().__init__(*args, **kwargs)
self.sneaky = sneaky
class Person:
def __init__(self, human = false, *args, **kwargs):
super().__init__(*args, **kwargs)
self.human = human
class Thief(Sneaky, Person):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
t = Thief(human = true, sneaky = true)
print(t.human)
# True
那么如果我们有下面的而不是删除 *args 呢?
class Sneaky:
def __init__(self, sneaky = false, **kwargs):
super().__init__( **kwargs)
self.sneaky = sneaky
class Person:
def __init__(self, human = false, **kwargs):
super().__init__(**kwargs)
self.human = human
class Thief(Sneaky, Person):
def __init__(self, **kwargs):
super().__init__( **kwargs)
t = Thief(human = true, sneaky = true)
print(t.human)
# True
传入*args
意味着你可以像
一样初始化你的Thief
>> x = Thief(True, False)
>> x.human
False
>> x.sneaky
True
这读起来很混乱,并且很难跟踪多重继承,但它可能很有用。保持这种能力意味着你可以做到
sneaky = (True, False, True,)
human = (True, False, False,)
thieves = [Thief(*args) for args in zip(sneaky, human)]
这有点做作,但我认为它说明了为什么您可能想要允许位置参数。
如果您确实想要删除 *args
并且不支持位置参数,您可以通过在 *,
之后添加 *,
将它们从 Sneaky
和 Person
中排除=19=].
class Sneaky:
def __init__(self, *, sneaky=False, **kwargs):
super().__init__(**kwargs)
self.sneaky = sneaky
class Person:
def __init__(self, *, human=False, **kwargs):
super().__init__(**kwargs)
self.human = human
这不会将所有位置参数放在 un-named *
中。如果您尝试提供位置参数,这将引发 TypeError
。
在第一种情况下,以下代码将输出 True
。
t = Thief(True, True)
print(t.human)
# True
但在第二个(没有 *args
) - 它会引发异常:
t = Thief(True, True) # arguments without keywords
print(t.human)
# raises
# TypeError: __init__() takes 1 positional argument but 3 were given
我对在 python 继承中的 super().__init__()
中传递 *args
的约定感到困惑。
我理解需要使用关键字参数 **kwargs
以便在需要时 CRO 中的 class 可以获取所需的参数,但为什么还有 *args
?
示例: 假设 Sneaky 被用作多重继承 class 结构的一部分,例如:
class Sneaky:
def __init__(self, sneaky = false, *args, **kwargs):
super().__init__(*args, **kwargs)
self.sneaky = sneaky
class Person:
def __init__(self, human = false, *args, **kwargs):
super().__init__(*args, **kwargs)
self.human = human
class Thief(Sneaky, Person):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
t = Thief(human = true, sneaky = true)
print(t.human)
# True
那么如果我们有下面的而不是删除 *args 呢?
class Sneaky:
def __init__(self, sneaky = false, **kwargs):
super().__init__( **kwargs)
self.sneaky = sneaky
class Person:
def __init__(self, human = false, **kwargs):
super().__init__(**kwargs)
self.human = human
class Thief(Sneaky, Person):
def __init__(self, **kwargs):
super().__init__( **kwargs)
t = Thief(human = true, sneaky = true)
print(t.human)
# True
传入*args
意味着你可以像
Thief
>> x = Thief(True, False)
>> x.human
False
>> x.sneaky
True
这读起来很混乱,并且很难跟踪多重继承,但它可能很有用。保持这种能力意味着你可以做到
sneaky = (True, False, True,)
human = (True, False, False,)
thieves = [Thief(*args) for args in zip(sneaky, human)]
这有点做作,但我认为它说明了为什么您可能想要允许位置参数。
如果您确实想要删除 *args
并且不支持位置参数,您可以通过在 *,
之后添加 *,
将它们从 Sneaky
和 Person
中排除=19=].
class Sneaky:
def __init__(self, *, sneaky=False, **kwargs):
super().__init__(**kwargs)
self.sneaky = sneaky
class Person:
def __init__(self, *, human=False, **kwargs):
super().__init__(**kwargs)
self.human = human
这不会将所有位置参数放在 un-named *
中。如果您尝试提供位置参数,这将引发 TypeError
。
在第一种情况下,以下代码将输出 True
。
t = Thief(True, True)
print(t.human)
# True
但在第二个(没有 *args
) - 它会引发异常:
t = Thief(True, True) # arguments without keywords
print(t.human)
# raises
# TypeError: __init__() takes 1 positional argument but 3 were given