【发布时间】:2019-12-18 17:12:21
【问题描述】:
我想在 python 中更多地使用 Mixins 并且喜欢以下模式:
class Person:
[...]
class Greetable:
greeting: str
def __init__(*args, **kwargs):
super().__init(*args, **kwargs)
... greeting related setup
def greet(self):
print(f"{self.greeting} sir or madam!")
class Sailor(Greetable, Person):
def __init__(self):
super().__init__()
self.greeting = "Ahoy"
>>> Sailor().greet()
"Ahoy sir or madam!"
但我还没有解决参数化混入的问题。在我的工作中,我看到很多明确的__init__ 调用超类alá
class A(B, FloorMixin):
def __init__(desk, chair, floor):
B.__init__(self, desk, chair)
FloorMixin.__init__(floor)
我看到了分解参数并显式分配它们的用途,但我想保留上述 Mixin 示例的 __init__ 的“passthrough”属性。
我只能考虑将 Mixin 的所有参数都作为特定的关键字参数,从 **kwargs 参数中获取 pop'ed 或者仅依赖于 mixin 中存在的字段并且必须在之前设置它们,这会将最后一个示例变成:
class A(FloorMixin, B):
def __init__(desk, chair, floor):
self._floor = floor # FloorMixin expects a _floor attribute
super().__init__(desk, chair)
【问题讨论】:
-
这基本上是Python's super() considered super! 中提出的建议:提取您将处理的参数,然后传递其余的。 (在对fuhm.net/super-harmful 的结论中重申了同样的建议,结果证明这与其说是反驳,不如说是对如何正确使用
super的进一步说明。) -
@chepner 这是否意味着,Mixins 不应该盲目地调用
super().__init__(*args, **kwargs),因为在这种情况下,构造函数可能会被多次调用? -
它们不会被多次调用,因为每个类只在方法解析顺序中出现一次。他们应该像任何其他类一样使用
super。 -
如果你从一个使用
super的类继承,你也应该使用super。如果你从一个不使用super的类继承,那么从你那里继承的任何东西都不应该使用super,除非你遵循从PSCS中的非合作类继承的建议。