在 Python 中,如何避免在派生自在其 __new__ 中带有 super() 的类的类中调用 __init__ 两次:

Ahs*_*Zeb 5 python derived-class super

我是python的新手。不知何故

__init__
Run Code Online (Sandbox Code Playgroud)

对于从另一个类派生的类调用两次

super()
Run Code Online (Sandbox Code Playgroud)

我的问题是如何避免这种情况,因为我在那里进行了非常昂贵的计算。

class A(object):
  def __new__(cls, *args, **kwargs):
    print("Class A: __new__")
    obj = super(A, cls).__new__(cls) # super is used here
    obj.__init__(*args, **kwargs)
    return obj
  def __init__(self, x):
    self.attrib = x+1

class B(A):
  def __init__(self, x):
    print("Class B: __init__")
    self.prop = 2*x # some expensive computation

a = A(10) # a test call

b = B(20) # Q: here, how to avoid calling __init__ twice in class B?
Run Code Online (Sandbox Code Playgroud)

编辑:谢谢两位的回答。我的真实代码是使用 scipy 库中内置的 arpack 对角化一个大型稀疏矩阵。我正在调用在 arpack.py 中定义的类 SpLuInv(LinearOperator),其中类 LinearOperator 在 interface.py 中定义,两个文件都附加:arpack.pyinterface.py。当我调用 SpLuInv() 时,它的init被调用了两次。从你的回答来看,我想我需要删除 obj. init在LinearOperator() 的new中。

感谢 Brendan Abel 的回答以及 Akshat Mahajan 和 Mike Graham 的评论。删除

obj.__init__
Run Code Online (Sandbox Code Playgroud)

来自

__new__
Run Code Online (Sandbox Code Playgroud)

LinearOperator()
Run Code Online (Sandbox Code Playgroud)

解决了这个问题。:)

Bre*_*bel 5

你不应该手动调用__init____new__。返回的对象__new__将自动__init__调用。

应该__init__所有类中调用超类,即使它们只继承自object.

唯一出现问题的情况是单例对象之类的东西,它们通常__init____new__. 在这种情况下,您只需将类的实例存储为类属性,并直接从__init__属性设置时返回。

class A(object):
    def __new__(cls, *args, **kwargs):
        print("Class A: __new__")
        obj = super(A, cls).__new__(cls) # super is used here
        return obj

    def __init__(self, x):
        super(A, self).__init__()
        self.attrib = x+1

class B(A):
    def __init__(self, x):
        print("Class B: __init__")
        super(B, self).__init__(x)
        self.prop = 2*x # some expensive computation
Run Code Online (Sandbox Code Playgroud)

  • Nit:如果“__new__”返回该类型的实例(包括子类),“metaclass.__call__”只会调用“__init__”。如果您重写 __new__` 以返回缓存的对象(那么 __init__` 必然会被多次调用)或不同类的对象(那么根本不会为您调用 __init__` ),这一点很重要。 (2认同)