python - correctly overloading the __add__ of a namedtuple -
i'm trying overload __add__
method on namedtuple instances , i'm having bit of trouble.
the parameters input namedtuples dynamically generated. 4 parameters same , in same order, rest can , in number. need able dynamically define namedtuple class factory. , after create several instances, i'd able add them new namedtuple instance, unique parameters together. having trouble overloading __add__
method. doesn't seem work.
so example, if have 3 namedtuple instances
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)
i'd able add them e + m + t
returns
row(a=1, b=2, c=3, d=4, param1='a', param2='b', param3='val', param4=10)
here current code
class row(object): ''' creates new namedtuple object ''' __slots__ = () def __new__(cls, *args, **kwargs): ''' make new row instance ''' default = namedtuple('row', 'a, b, c, d') newcols = set(args) - set(default._fields) finalfields = default._fields + tuple(newcols) if newcols else default._fields return namedtuple('row', finalfields) def __add__(self, other): ''' new add ''' self_dict = self._asdict() other_dict = other._asdict() self_dict.update(other_dict) new_fields = tuple(self_dict.keys()) new_row = namedtuple('row', new_fields) return new_row(**self_dict)
with this, can correctly dynamically generate new namedtuples, , instantiate them
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')
but when add them, overloaded __add__
never gets called , seem regular tuple object out
w = e2 + m2 print(w) (1, 2, 3, 4, 1, 2, 3, 4, 'a', 'b') type(w) tuple
my __add__
method doesn't seem active on instance objects.
row.__add__? signature: row.__add__(self, other) docstring: 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 @ 0x122614050> docstring: x.__add__(y) <==> x+y
what doing wrong? tried subclassing namedtuple('row', ...), indicated in docs https://docs.python.org/2/library/collections.html#collections.namedtuple, couldn't work. couldn't dynamically change named parameters.
here failure
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 unexpected keyword argument 'param1'
the __add__
method defined method accessible instances of class type row
.
when overrode __new__
method of row
class, return object of type namedtuple(...)
, not row
. therefore, further manipulation of objects not have access __add__
method because not row
s, namedtuple()
s.
as @user2357112 mentioned, seems you're making things difficult , may better off using dictionaries. if need immutable, hashable type each of rows can create sets , use them dictionary keys, convert dictionaries named tuples right before using them way.
Comments
Post a Comment