我想我还没有理解如何定义从 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)

任何想法为什么?

最佳答案

实例构造函数 ( __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__ 初始值设定项;所有内置的不可变( frozensetstrtuple )都这样做。

关于python - 无法初始化子类命名元组的实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12745671/

10-16 02:55