2012-10-05 70 views
3

的實例,我想我還沒有undertood如何定義從namedtuple子類的類:不能初始化一個子類namedtuple

from collections import namedtuple 
PD = namedtuple('PD', 'x y z') 
p1 = PD(0, 'u', 1) 
print p1.x #<== this works 

class PDsub(PD): 
    __slots__ =() 
    def __new__(cls, x, y, z): 
     self = super(PDsub, cls).__new__(cls, x, y, z) 
     return self 

    def __init__(self, a): 
     self.x, self.y, self.z = a, a, a 

    def __str__(self): 
     return 'Foo' 

p2 = PDsub(5) #<== this does not work 

此代碼引發TypeError : __new__() takes exactly 4 arguments (2 given)

任何想法爲什麼?

+2

__new__被__init__其被期待多個參數之前調用。 new和init需要有完全相同數量的參數。 – karthikr

回答

5

實例構造函數(__new__)和實例初始值設定項(__init__)都需要接受相同數量的參數。

__new__需要4個參數,但你__init__方法只接受2,調整一個或另一個接受相同的號碼,或在您的__init__方法使用*args包羅萬象的說法。

例如,使用下面的方法__new__會使事情的工作:

def __new__(cls, a): 
    self = super(PDsub, cls).__new__(cls, a, a, a) 
    return self 

在這種情況下,您不再需要你__init__初始化在所有

演示:

>>> from collections import namedtuple 
>>> PD = namedtuple('PD', 'x y z') 
>>> class PDsub(PD): 
...  __slots__ =() 
...  def __new__(cls, a): 
...   self = super(PDsub, cls).__new__(cls, a, a, a) 
...   return self 
...  def __str__(self): 
...   return 'Foo' 
... 
>>> p2 = PDsub(5) 
>>> p2.x, p2.y, p2.z 
(5, 5, 5) 
>>> str(p2) 
'Foo' 

一個不可變型等的元組經常使用__new__構造一個__init__初始化的代替;所有內置的不可變項(frozensetstr,tuple)都這樣做。

+0

好的,非常感謝!現在很清楚。 –

2
def __new__(cls, x, y, z): 

p2 = PDsub(5) 

當你創建你的類,__new__方法(構造函數)的對象調用來創建它。所以,在這裏你__new__方法需要4個參數,但你只有通過2(*注: - 參數cls是隱含的)

所以,要麼你改變你的__new__採取2參數,或者你可以改變你__init__4參數,並通過傳遞3參數相應創建your instance(第一一個是隱式的。)