在python3中正确覆盖__new__

时间:2017-12-01 22:18:16

标签: python oop inheritance python-3.5 factory-pattern

所以我尝试覆盖__new__并让它作为工厂存在来创建 派生实例。在阅读了SO之后,我的印象是我应该在派生实例上调用__new__

BaseThing

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

    # methods to be derived

ThingFactory

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)

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)

但我认为这不是__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。我一定做错了。

在我看来,我需要直接在我的基地继承对象,但有人能解释这样做的正确方法吗?

1 个答案:

答案 0 :(得分:1)

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

instance = super().__new__(A)

我无法保证这足以解决您的问题,因为您发布的代码无法重现您声称的错误;它有其他问题会导致首先出现不同的错误(无限递归)。特别是,如果AB并非真正来自Thing,则需要进行不同的处理。