Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where should I define namedtuple classes in Python - which namespace?

Namedtuples are useful in Python to name small collections of data.

Take for example this namedtuple:

import collections
sesameEpisodeNTC = collections.namedtuple('sesameEpisodeNTC', 
                                          'lead_character', 'has_elmo')
se0 = sesameEpisodeNTC(lead_character='bigbird', has_elmo=False)

Can the class definition ('sesameEpisodeNTC = '...) be made an attribute of another class? I'd prefer to keep some namedtuples inside classes to avoid cluttering the module namespace. But this causes problems with pickling (cPickle, dill), which is a showstopper.

Similarly, I've noticed the first parameter of the namedtuple class definition, the typename (i.e. 'sesameEpisodeNTC') must be the name of the class, otherwise pickling does not work. (using both 2.7 and 3.4) That duplication is not ideal. Are there other best practices for the typename parameter, and does it affect code beside pickling code?

Are there other not-widely-documented corner cases I'm missing with namedtuples? It's annoying that some of python's most useful data structures have sharp corners that can snag on parts of the stdlib.

like image 699
MHH Avatar asked Nov 09 '22 15:11

MHH


1 Answers

If you make the namedtuple definition at the module level, dill can pickle the class with the namedtuple class object as an attribute. Of course, this doesn't help you "reduce clutter". I think the answer is no. At the moment, you can not define a namedtuple inside a class and have it pickled by default.

>>> import collections
>>> nt = collections.namedtuple('nt',['one','two'])
>>> nt
<class '__main__.nt'>
>>> 
>>> import dill
>>> 
>>> dill.copy(nt)
<class '__main__.nt'>
>>> 
>>> class Foo(object):
...   cnt = nt
... 
>>> f = Foo()
>>> f.cnt
<class '__main__.nt'>
>>> f.cnt(1,2)
nt(one=1, two=2)
>>> 
>>> dill.copy(f)
<__main__.Foo object at 0x10f1b5850>
>>> dill.copy(Foo)
<class '__main__.Foo'>
>>> 

There is a ticket/issue on dill github to be able to do better, but right now no -- you'd have to live with module-level namedtuples -- and yes, they need to have the same name as the first parameter of the namedtuple.

like image 146
Mike McKerns Avatar answered Nov 14 '22 21:11

Mike McKerns