2012-10-05 69 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(第一一个是隐式的。)