__new __()没有返回类的实例时的继承

时间:2015-02-08 10:17:09

标签: 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

但是,

  

如果__new__()未返回cls的实例,则返回新的__init__()   

。实例的__init__()方法不会被调用。

我们必须直接在__new__()内调用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

如何解决?如果A.__new__()没有返回类的实例,如何创建{{1}}的子类?

1 个答案:

答案 0 :(得分:1)

如果您要手动调用它,请不要命名方法__init__并改为使用每个类名称,手动调用__init__方法没有约束,直接在课堂上。

每个类名称相对容易,您可以在开头使用双下划线来通过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

毕竟,你已经在创建时有权访问该实例,你也可以在那里初始化它。