Sublassing tuple works, subclassing list does not

Carl Banks pavlovevidence at gmail.com
Wed Mar 31 11:38:33 CEST 2010


On Mar 31, 2:02 am, Rob Williscroft <r... at rtw.me.uk> wrote:
> Frank Millman wrote in news:mailman.1360.1270018159.23598.python-
> l... at python.org in comp.lang.python:
>
> > I came up with a simple solution that seems to work -
>
> >>>> class MyTuple(tuple):
> > ...   def __new__(cls, names, values):
> > ...     for name, value in zip(names, values):
> > ...       setattr(cls, name, value)
> > ...     return tuple.__new__(cls, values)
> > ...
> >>>> names = ['A', 'B', 'C']
> >>>> values = ['a', 'b', 'c']
>
> >>>> tup = MyTuple(names, values)
>
> Are you aware you are adding attributes to the class here, IOW:
>
>         MyTuple.C == 'c'



> If you want to add attibutes to the instance:
>
> class MyTuple(tuple):
>   def __new__(cls, names, values):
>     r =  tuple.__new__(cls, values)
>     for name, value in zip(names, values):
>       setattr(r, name, value)
>     return r
>
> names = ['A', 'B', 'C']
> values = ['a', 'b', 'c']
>
> tup = MyTuple(names, values)
>
> assert tup[0] == 'a'
> assert tup.B == 'b'
>
> try:
>   MyTuple.C
> except AttributeError:
>   pass
> else:
>   assert False

Careful, this adds the new attributes as to the object's __dict__, not
to the tuple item slots.  Which works ok if you don't care if that
someone can mutate the attributes, and if they do the attributes no
longer match the items.  Personally I do mind.

tup = MyTuple(names,values)
assert tup.A == 'a'
assert tup[0] == 'a'
tup.A = 'd'    # doesn't fail but should
assert tup.A == 'd'
assert tup[0] == 'd'   # fails but, granted you allow mutabilty,
shouldn't



The best way to do what the OP wanted (originally) is this, no
subclassing necessary:

def my_named_tuple(names,values):
    return namedtuple('ad_hoc_named_tuple',names)(*values)


As for the OP's second problem, to append named items, I'd first
consider whether I'm thinking about the problem correctly, and if so,
go with a subclass of list and overriding __getattr__.  Probably one
of the rare cases I would override __getattr__ other than a proxy
class.


Carl Banks



More information about the Python-list mailing list