我似乎无法实例化一个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).