我有一个简单的基类,它实例化为两个子类之一:
class Base:
def __new__(cls, select):
return super().__new__(Child1 if select == 1 else Child2)
def __init__(self, select):
self.select = select
def __repr__(self):
return f'{type(self).__name__}({self.select})'
class Child1(Base):
def __init__(self):
super().__init__('One')
class Child2(Base):
def __init__(self):
super().__init__('Two')
这当前会引发错误,因为子
__init__
方法不带参数,而父 __new__
则带参数:
>>> Base(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes 1 positional argument but 2 were given
我可以通过在新的元类中覆盖
type.__call__
来解决这个问题,但我想保留 type
作为我的元类。
我还可以将
select
或 *args
作为参数添加到子 __init__
方法中。有没有一种更优雅的方法来实现相同的目的,即允许子级 __init__
使用与父级 __new__
接受的参数不同的参数运行?
恐怕这是不可能的,至少用比元类更“优雅”的方式是不可能的。在较旧的Python中,可以将参数传递给
super().__new__
,但实际上从未使用过它们,因此该行为已被弃用并在后来被删除。
该消息的意思就是它所说的。 :-) 打电话没有意义 object.__new__() 具有多个类参数,以及任何代码 这样做只是将这些参数扔进黑洞。
object.__new__() 忽略额外的唯一有意义的时候 参数是当它没有被覆盖,但 __init__ is 被覆盖时 覆盖——那么你就有了一个完全默认的 new 和 构造函数参数的检查被降级为 init。
这一切的目的是捕获像这样的调用中的错误 object(42)(再次)传递一个未使用的参数。这是 通常是程序中存在错误的症状。