我试图在namedtuple实例上重载__add__
方法,但有点麻烦。在
输入到namedtuples中的参数是动态生成的。四个参数总是相同且顺序相同,但其余的参数可以是任意数量的任何参数。所以我需要能够动态定义我的namedtuple类工厂。在我创建了几个实例之后,我希望能够将它们一起添加到一个新的namedtuple实例中,并将所有惟一的参数一起添加到一起。但是我无法正确重载__add__
方法。好像不管用。在
例如,如果我有3个namedtuple实例
e = Row(a=1, b=2, c=3, d=4)
m = Row(a=1, b=2, c=3, d=4, param1='a', param2='b')
t = Row(a=1, b=2, c=3, d=4, param3='val', param4=10)
我希望能够像e + m + t
那样添加它们,它返回
Row(a=1, b=2, c=3, d=4, param1='a', param2='b', param3='val', param4=10)
这是我当前的代码
^{pr2}$有了它,我可以正确地动态生成新的namedtuples,并实例化它们
e = Row()
m = Row(*['a', 'b', 'c', 'd', 'param1', 'param2'])
e._fields
('a', 'b', 'c', 'd')
m._fields
('a', 'b', 'c', 'd', 'param1', 'param2')
e2 = e(1, 2, 3, 4)
m2 = m(1, 2, 3, 4, 'a', 'b')
e2
Row(a=1, b=2, c=3, d=4)
type(e2)
__main__.Row
m2
Row(a=1, b=2, c=3, d=4, param1='a', param2='b')
但是当我添加它们时,重载的__add__
永远不会被调用,我似乎只是得到了一个普通的元组对象
w = e2 + m2
print(w)
(1, 2, 3, 4, 1, 2, 3, 4, 'a', 'b')
type(w)
tuple
我的__add__
方法在我的实例对象上似乎不活动。在
Row.__add__?
Signature: Row.__add__(self, other)
Docstring: This is the new add
File: <ipython-input-535-817d9f528ae7>
Type: instancemethod
e.__add__?
Type: wrapper_descriptor
String form: <slot wrapper '__add__' of 'tuple' objects>
Docstring: x.__add__(y) <==> x+y
e2.__add__?
Type: method-wrapper
String form: <method-wrapper '__add__' of Row object at 0x122614050>
Docstring: x.__add__(y) <==> x+y
我做错什么了?我还尝试了namedtuple('Row',…)的子类化,如docshttps://docs.python.org/2/library/collections.html#collections.namedtuple所示,但我无法使其工作。我无法让它动态更改命名参数。在
这就是失败
BaseRow = namedtuple('BaseRow', 'a, b, c, d')
class Row(BaseRow):
__slots__ = ()
def __new__(cls, *args, **kwargs):
new_fields = set(kwargs.keys()) - set(cls._fields)
cls._fields += tuple(new_fields)
obj = super(Row, cls).__new__(cls, *args, **kwargs)
return obj
e = Row(a=1, b=2, c=3, d=4, param1='a')
TypeError: __new__() got an unexpected keyword argument 'param1'
谢谢你的回复。我被迫使用namedtuples,因为我处理的是SQLAlchemy返回的结果,它以KeyedTuples的形式返回,这是它们的namedtuples版本。所以我必须使用namedtuple,这样我的通用函数就可以同时使用这两个函数。我敢肯定这打破了元组的整个风气。在
对于后人来说,我就是这样解决的。由于namedtuple实际上只是一个生成类的函数,所以我只编写了自己的函数,它将以相同的方式动态生成一个新的namedtuple对象,并将
__add__
方法重载到每个生成的类中。在它是这样使用的
^{pr2}$您定义的
__add__
方法是一个只有类类型Row
的实例才能访问的方法。在重写
Row
类的__new__
方法时,返回一个namedtuple(...)
类型的对象,而不是Row
。因此,对这些对象的进一步操作将无法访问您的__add__
方法,因为它们不是Row
s,而是namedtuple()
s正如一个@user2357112所提到的,似乎你在给自己制造麻烦,而仅仅使用字典可能会更好。如果您需要为每一行提供一个不可变的散列类型,以便可以创建集合并将它们用作字典键,请在使用之前将字典转换为命名元组。在
相关问题 更多 >
编程相关推荐