python - __new__() 不返回类实例时的继承

标签 python python-3.x constructor initializer

__new__返回类的实例时,一切正常,我们可以毫无问题地创建子类:

class A:
    def __new__(cls, p1, p2):
        self = object.__new__(cls) 
        return self

    def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2

class B(A):
    def __new__(cls, p3):
        self = super().__new__(cls, 1, 2)
        return self

    def __init__(self, p3):
        super().__init__(1, 2)
        self.p3 = p3

a = A(1, 2)    
print(a.p2)  # output: 2

b = B(3)
print(b.p3)  # output: 3

但是,

If __new__() does not return an instance of cls, then the new instance’s __init__() method will not be invoked.

看起来我们必须直接在 __new__() 内部调用 __init__() ,但这会导致错误,当我们调用 super().__new__ 在子类中:

class A:
    def __new__(cls, p1, p2):
        self = object.__new__(cls)
        self.__init__(p1, p2)  # we should call __init__ directly
        return [self]  # return not instance

    def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2

class B(A):
    def __new__(cls, p3):
        self = super().__new__(cls, 1, 2)
        return self

    def __init__(self, p3):
        self.p3 = p3

a = A(1, 2)    
print(a[0].p2)  # output: 2

b = B(3)  # TypeError: __init__() takes 2 positional arguments but 3 were given
print(b[0].p3)

如何解决?如果A.__new__()不返回类的实例,如何创建A的子类?

最佳答案

如果您要手动调用它,请不要命名该方法 __init__ 并使用每个类的名称,手动调用 __init__ 方法未绑定(bind),直接在类上。

每个类的名称相对简单,您可以在开头使用双下划线通过 name mangling 生成特定于类的名称。 :

class A:
    def __new__(cls, p1, p2):
        self = object.__new__(cls)
        self.__init(p1, p2)  # call custom __init directly
        return [self]  # return not instance

    def __init(self, p1, p2):
        self.p1 = p1
        self.p2 = p2

class B(A):
    def __new__(cls, p3):
        self = super().__new__(cls, 1, 2)
        self[0].__init(p3)  # custom init
        return self

    def __init(self, p3):
        self.p3 = p3

或直接在类里面:

class A:
    def __new__(cls, p1, p2):
        self = object.__new__(cls)
        A.__init__(self, p1, p2)  # call custom __init__ unbound
        return [self]  # return not instance

    def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2

class B(A):
    def __new__(cls, p3):
        self = super().__new__(cls, 1, 2)
        B.__init__(self[0], p3)  # call custom __init__ unbound
        return self

    def __init__(self, p3):
        self.p3 = p3

如果您要这样做,您也可以放弃自定义初始化程序,而只在 __new__ 中进行初始化:

class A:
    def __new__(cls, p1, p2):
        self = object.__new__(cls)
        self.p1 = p1
        self.p2 = p2
        return [self]  # return not instance


class B(A):
    def __new__(cls, p3):
        self = super().__new__(cls, 1, 2)
        self[0].p3 = p3
        return self

毕竟,您在创建时已经可以访问实例,您也可以当场初始化它。

关于python - __new__() 不返回类实例时的继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28392810/

相关文章:

python - 使用分类变量作为 PyMC3 中其他参数的索引

python-3.x - Kivy:弹出窗口只能有一个小部件作为内容

python - 找到目标后如何停止线程?

c++ - 无法将引用从一个类传递到另一个类

c++ - 基类构造函数参数与派生类构造函数之间的关系

python - 使用自定义搜索以编程方式在 Python 中搜索 google

Python编码——如何在列表的列表中找到特定元素的踪迹?

python 使用 *args 和 **kwargs 以及其他位置参数和仅关键字参数解包 arg 列表

C++ primer 说我们可以为 "=default"构造函数使用初始化列表

python列拆分