如何在没有元类的情况下将不同的参数传递给 __new__ vs __init__
How to pass different arguments to __new__ vs __init__ without a metaclass
我有一个简单的基础 class 实例化为两个 child classes:
之一
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')
这目前引发了一个错误,因为 child __init__
方法没有参数,而 parent __new__
有:
>>> Base(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes 1 positional argument but 2 were given
我可以通过在新元 class 中覆盖 type.__call__
来解决这个问题,但我想保留 type
作为我的元 class。
我还可以将 select
或 *args
作为参数添加到 child __init__
方法中。是否有更优雅的方法来实现允许 child __init__
到 运行 与 parent __new__
接受的不同参数?
恐怕这是不可能的,至少比元类多 'elegant' 方式。在较旧的 python 中,可以将参数传递给 super().__new__
,但实际上从未使用过,因此该行为 was deprecated 并在以后完全删除。
The message means just what it says. :-) There's no point in calling
object.new() with more than a class parameter, and any code that
did so was just dumping those args into a black hole.
The only time when it makes sense for object.new() to ignore extra
arguments is when it's not being overridden, but init is being
overridden -- then you have a completely default new and the
checking of constructor arguments is relegated to init.
The purpose of all this is to catch the error in a call like
object(42) which (again) passes an argument that is not used. This is
often a symptom of a bug in your program.
我有一个简单的基础 class 实例化为两个 child classes:
之一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')
这目前引发了一个错误,因为 child __init__
方法没有参数,而 parent __new__
有:
>>> Base(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes 1 positional argument but 2 were given
我可以通过在新元 class 中覆盖 type.__call__
来解决这个问题,但我想保留 type
作为我的元 class。
我还可以将 select
或 *args
作为参数添加到 child __init__
方法中。是否有更优雅的方法来实现允许 child __init__
到 运行 与 parent __new__
接受的不同参数?
恐怕这是不可能的,至少比元类多 'elegant' 方式。在较旧的 python 中,可以将参数传递给 super().__new__
,但实际上从未使用过,因此该行为 was deprecated 并在以后完全删除。
The message means just what it says. :-) There's no point in calling object.new() with more than a class parameter, and any code that did so was just dumping those args into a black hole.
The only time when it makes sense for object.new() to ignore extra arguments is when it's not being overridden, but init is being overridden -- then you have a completely default new and the checking of constructor arguments is relegated to init.
The purpose of all this is to catch the error in a call like object(42) which (again) passes an argument that is not used. This is often a symptom of a bug in your program.