I think I have not undertood how to define a class subclassed from a 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
This code raises TypeError : __new__() takes exactly 4 arguments (2 given)
.
Any ideas why?
Whenever you create an object for your class,
__new__
method (constructor) is called to create it.. So, here your__new__
method requires 4 parameters, but you have only passed 2 (*Note: - parametercls
is implicit)So, either you change your
__new__
to take 2 parameters, or you can change your__init__
to take 4 parameters, and accordingly createyour instance
by passing 3 parameters (1st one is implicit..)Both the instance constructor (
__new__
) and your instance initializer (__init__
) need to accept the same number of arguments.Your
__new__
needs 4 arguments, but your__init__
method only accepts 2. Adjust one or the other to accept the same number, or use a*args
catch-all argument in your__init__
method.For example, using the following
__new__
method would make things work:in which case you no longer need your
__init__
initializer at all.Demo:
An immutable type like a tuple often uses a
__new__
constructor instead of a__init__
initializer; all the built-in immutables (frozenset
,str
,tuple
) do so.