我想我还没有理解如何从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)
。
任何想法为什么?
答案 0 :(得分:6)
实例构造函数(__new__
)和实例初始值设定项(__init__
)都需要接受相同数量的参数。
您的__new__
需要4个参数,但您的__init__
方法只接受2.调整一个或另一个接受相同的数字,或者在您的*args
全能参数中使用__init__
方法。
例如,使用以下__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__
初始值设定项;所有内置的不可变项(frozenset
,str
,tuple
)都这样做。
答案 1 :(得分:2)
def __new__(cls, x, y, z):
p2 = PDsub(5)
每当你为你的类创建一个对象时,都会调用__new__
方法(构造函数)来创建它。所以,这里你的__new__
方法需要4个参数,但你只传递了2个(*注意: - 参数 cls
是隐含的)
因此,您可以更改 __new__
以获取 2个参数,也可以更改 __init__
采用 4个参数,并相应地通过传递 3个参数来创建your instance
(第一个是隐式的......)