我的多重继承能力不强。我正在尝试创建一个父类(super class),其 __init__
采用可选的命名参数和它的子类,这些子类也继承自内置类型。可悲的是,我似乎不知道如何进行这项工作:
>>> class Super(object):
name = None
def __init__(self, *args, name=None, **kwargs):
self.name = name
super().__init__(self, *args, **kwargs)
>>> class Sub(Super, int):
pass
>>> Sub(5)
5
>>> Sub(5, name="Foo")
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
Sub(5, name="Foo")
TypeError: 'name' is an invalid keyword argument for this function
(我也尝试过不调用 super()
,但结果是一样的。)
也许对多重继承有更好了解的人可以为我指明正确的方向?
更新:
这是我最终得到的解决方案,基于 Alex's answer .
它仍然有点 hacky(通过在构建过程中更改 __new__
的签名),但只要父类(super class)出现在子类的 MRO 中并定义内置类型之前,它就可以工作__new__
这种方式让我可以创建使用不同内置类型的子类,而无需为每个类型添加单独的 __new__
。
>>> class Super(object):
name = None
def __new__(cls, *args, name=None, **kwargs):
inner = super().__new__(cls, *args, **kwargs)
inner.name = name
return inner
>>> class Sub(Super, int):
pass
>>> Sub(5)
5
>>> Sub(5, name="Foo")
5
>>> _.name
'Foo'
最佳答案
你不能将任意参数(无论是位置参数还是命名参数)传递给同样任意的父类(super class)(即“无论当前叶类型是什么,mro
中的前一个类型”)——大多数类型和类只是不接受任意参数,这也是出于极好的原因——引用自 Zen of Python
的中间部分,
Errors should never pass silently.
Unless explicitly silenced.
在大多数情况下,调用(例如)int(name='booga')
当然会出错。
如果你想让你的名字怪异的 class Super
能够“传递”任意参数,你还必须确保所有用作基础的类都可以处理 - 所以,例如,int
可以用一个参数(或恰好两个:一个字符串和一个基数)调用,因此,如果 class Sub
对您来说绝对重要可以从推卸责任的 Super
和 int 中乘以继承,你必须填写它,例如:
class Int(int):
def __new__(cls, *a, **k):
return int.__new__(Int, a[0] if a else 0)
请注意,您必须覆盖 __new__
,不能 __init__
(如果您也覆盖后者,但它无论如何都不相关):int
是不可变的,因此必须在 __new__
时间设置该值。
现在,比如
>>> class X(Super, Int): pass
...
>>> X(23, za='zo')
23
>>>
工作。但请注意 X
必须是 Int
的子类(我们的 __new__
- int
的净化版本),不是 来自 int
本身,它有一个无情的 __new__
!-)
关于python - 向内置类型的多重继承子类的构造函数添加可选参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3748635/