如何在没有元类的情况下将不同的参数传递给 __new__ 与 __init__

问题描述 投票:0回答:1

我有一个简单的基类,它实例化为两个子类之一:

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 inheritance constructor initialization
1个回答
2
投票

恐怕这是不可能的,至少用比元类更“优雅”的方式是不可能的。在较旧的Python中,可以将参数传递给

super().__new__
,但实际上从未使用过它们,因此该行为已被弃用并在后来被删除。

该消息的意思就是它所说的。 :-) 打电话没有意义 object.__new__() 具有多个类参数,以及任何代码 这样做只是将这些参数扔进黑洞。

object.__new__() 忽略额外的唯一有意义的时候 参数是当它没有被覆盖,但 __init__ is 被覆盖时 覆盖——那么你就有了一个完全默认的 new 和 构造函数参数的检查被降级为 init

这一切的目的是捕获像这样的调用中的错误 object(42)(再次)传递一个未使用的参数。这是 通常是程序中存在错误的症状。

© www.soinside.com 2019 - 2024. All rights reserved.