当 __new__() 不是 return class 实例时的继承

Inheritance when __new__() doesn't return instance of class

__new__ return 实例 class 时,一切正常,我们可以毫无问题地创建子 class:

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__(),但这会导致错误,当我们在子class中调用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__() 不是 return class 的实例,如何创建 A 的子 class?

如果您要手动调用它,要么不要命名方法 __init__ 而是使用每个 class 名称,手动 直接在 class.

上调用未绑定的 __init__ 方法

Per-class 名称相对容易,您可以在开头使用双下划线通过 name mangling:

生成 class-specific 名称
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:

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

毕竟,您已经在创建时就可以访问该实例,您最好立即对其进行初始化。