cannot init an instance of a subclassed namedtuple

耗尽温柔 提交于 2019-12-22 08:18:22

问题


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?


回答1:


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:

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

in which case you no longer need your __init__ initializer at all.

Demo:

>>> 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'

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.




回答2:


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

p2 = PDsub(5)

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: - parameter cls is implicit)

So, either you change your __new__ to take 2 parameters, or you can change your __init__ to take 4 parameters, and accordingly create your instance by passing 3 parameters (1st one is implicit..)



来源:https://stackoverflow.com/questions/12745671/cannot-init-an-instance-of-a-subclassed-namedtuple

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!