正确覆盖python3中的__new__ [英] correctly override __new__ in python3

查看:81
本文介绍了正确覆盖python3中的__new__的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我试图覆盖__new__并将其作为工厂存在以进行创建 派生实例.在对SO有所了解之后,我觉得我也应该在派生实例上调用__new__.

So I am trying to override __new__ and let it exist as a factory to create derived instances. After reading a bit on SO, I am under the impression that I should be calling __new__ on the derived instance as well.

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)

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)

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

I am bit confused by this; when I just return a concrete instance of derived classes, it just worked. i.e.

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

但是我不认为这是返回__new__的正确方法;可能会将呼叫复制到__init__.

I however don't think this it the correct way of returning in __new__; it may duplicate the calls to __init__.

当我在object中检查__new__的签名时,似乎是这样的:

when I am checking signatures of __new__ in object it seems be this one:

@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.我一定在这里做错了.

I didn't expect this was the one; I'd expect it came with args and kwargs as well. I must have done something wrong here.

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

it seems to me that I need to inherit object directly in my base but could anyone explain the correct way of doing it?

推荐答案

您在呼叫__new__错误.如果要__new__创建子类的实例,则不要调用子类的__new__;您可以照常调用超类的__new__,但是将其传递给子类作为第一个参数:

You're calling __new__ wrong. If you want your __new__ to create an instance of a subclass, you don't call the subclass's __new__; you call the superclass's __new__ as usual, but pass it the subclass as the first argument:

instance = super().__new__(A)

我不能保证这足以解决您的问题,因为您发布的代码不会重现您声明的错误;它还有其他会首先导致不同错误的问题(无限递归).特别是,如果AB并不是真正地从Thing衍生而来,则需要不同的处理方式.

I can't guarantee that this will be enough to fix your problems, since the code you've posted wouldn't reproduce the error you claim; it has other problems that would have caused a different error first (infinite recursion). Particularly, if A and B don't really descend from Thing, that needs different handling.

这篇关于正确覆盖python3中的__new__的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆