正确覆盖python3中的__new__

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

所以我试图覆盖

__new__
并让它作为工厂存在来创建 派生实例。在阅读了一些关于 SO 的内容之后,我的印象是我也应该在派生实例上调用
__new__

基础事物

class BaseThing:
    def __init(self, name, **kwargs):
        self.name = name

    # methods to be derived

事物工厂

class Thing(BaseThing):
    def __new__(cls, name, **kwargs):
        if name == 'A':
           return A.__new__(name, **kwargs)
        if name == 'B':
           return B.__new__(name, **kwargs)        

    def __init__(self, *args, **kwargs):
        super().__init__(name, **kwargs)

   # methods to be implemented by concrete class (same as those in base)

A

class A(BaseThing):
    def __init__(self, name, **kwargs):
       super().__init__(name, **kwargs)

B

class B(BaseThing):
    def __init__(self, name, **kwargs):
       super().__init__(name, **kwargs)
 

我所期待的是它会起作用。

>>> a = Thing('A')

给了我

TypeError: object.__new__(X): X is not a type object (str)

我对此有点困惑;当我只返回派生类的具体实例时,它就起作用了。即

def __new__(cls, name, **kwargs):
        if name == 'A':
           return A(name)
        if name == 'B':
           return B(name)

我认为这不是

return
__new__
的正确方法;它可能会重复调用
__init__

当我检查

__new__
object
的签名时,似乎是这个:

@staticmethod # known case of __new__
def __new__(cls, *more): # known special case of object.__new__
    """ Create and return a new object.  See help(type) for accurate signature. """
    pass

没想到就是这个;我希望它也带有 args 和 kwargs 。我一定是在这里做错了什么。

在我看来,我需要直接在我的基础中继承对象,但有人可以解释正确的方法吗?

python oop inheritance python-3.5 factory-pattern
1个回答
11
投票

你打错了

__new__
。如果您希望
__new__
创建子类的实例,则不要调用子类的
__new__
;你像往常一样调用超类的
__new__
,但是 将子类作为第一个参数传递给它:

instance = super().__new__(A)

我不能保证这足以解决您的问题,因为您发布的代码不会重现您声称的错误;它还有其他问题,这些问题首先会导致不同的错误(无限递归)。特别是,如果

A
B
并不是真正从
Thing
下降,则需要不同的处理。

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