python - 无法创建 namedtuple 子类的实例 : TypeError: __new__() takes exactly 4 arguments (3 given)

标签 python python-2.7 namedtuple

我似乎无法实例化一个 namedtuple 子类:

from collections import namedtuple

foo = namedtuple("foo",["a","b","c"])
class Foo(foo):
    def __init__(self, a, b):
        super(Foo, self).__init__(a=a,b=b,c=a+b)

当我尝试创建一个实例时,我得到:

>>> Foo(1,2)
TypeError: __new__() takes exactly 4 arguments (3 given)

我期望 Foo(1,2,3)

似乎有一个解决方法:使用类方法代替 __init__:

class Foo(foo):
    @classmethod
    def get(cls, a, b):
        return cls(a=a, b=b, c=a+b)

现在 Foo.get(1,2) 确实返回了 foo(a=1, b=2, c=3)

但是,这看起来很难看。

这是唯一的方法吗?

最佳答案

命名元组不可变,您需要使用__new__ method相反:

class Foo(foo):
    def __new__(cls, a, b):
        return super(Foo, cls).__new__(cls, a=a, b=b, c=a+b)

(注意:__new__ 隐含地成为一个静态方法,因此您需要显式传递 cls 参数;该方法返回新创建的实例)。

__init__ 无法使用,因为它是在实例创建之后调用的,因此无法再改变元组。

请注意,您确实应该向子类添加 __slots__ = () 行;一个命名的元组没有 __dict__ 字典使你的内存困惑,但你的子类除非你添加 __slots__ 行:

class Foo(foo):
    __slots__ = ()
    def __new__(cls, a, b):
        return super(Foo, cls).__new__(cls, a=a, b=b, c=a+b)

这样您就可以将命名元组的内存占用保持在较低水平。查看__slots__文档:

The action of a __slots__ declaration is limited to the class where it is defined. As a result, subclasses will have a __dict__ unless they also define __slots__ (which must only contain names of any additional slots).

关于python - 无法创建 namedtuple 子类的实例 : TypeError: __new__() takes exactly 4 arguments (3 given),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48529355/

相关文章:

python - 查找两点之间字符串的最佳方法

python - 在没有临时文件的情况下将 JPEG 从 URL 加载到 skimage

将字典转换为 namedtuple 或其他类似哈希的字典的 Pythonic 方法?

python - 了解 Python 中 namedtuple typename 和 pickle 的问题

python - 将 Timedelta 从 Pandas Dataframe 转换为秒值

python - 如何将 lambda append 到 python 中的列表?

Python 2.7 和 PyDev - matplotlib 和 NumPy 不起作用

python-2.7 - pandas.DataFrame.to_pickle 向后兼容性

python - 获取Python中字典字典中所有键的数量

python - 使用带有填充的命名元组列表的字符串格式进行 pretty-print (Python)