Sublassing tuple works, subclassing list does not

lbolla lbolla at gmail.com
Wed Mar 31 04:18:39 EDT 2010


On Mar 31, 7:49 am, "Frank Millman" <fr... at chagford.com> wrote:
> Hi all
>
> I needed something similar to, but not quite the same as,
> collections.namedtuple.
>
> The differences are that namedtuple requires the 'names' to be provided at
> creation time, and then lends itself to creating multiple instances of
> itself. I wanted a more generic class where I could supply the 'names' and
> 'values' at instantiation time.
>
> 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)
>
> >>> print tup
> ('a', 'b', 'c')
>
> >>> print tup[0]
> a
>
> >>> print tup.B
> b
>
> Then I had a need to add elements after the tuple had been created. As
> tuples are immutable, I thought it would be easy to change it to a list.
> However, it does not work -
>
> >>> class MyList(list):
>
> ...   def __new__(cls, names, values):
> ...     for name, value in zip(names, values):
> ...       setattr(cls, name, value)
> ...     return list.__new__(cls, values)
> ...>>> names = ['A', 'B', 'C']
> >>> values = ['a', 'b', 'c']
>
> >>> lst = MyList(names, values)
>
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: list() takes at most 1 argument (2 given)
>
>
>
> I can find a workaround, but I would be interested to know the reason why it
> does not work.
>
> Version is 2.6.2.
>
> Thanks
>
> Frank Millman

When subclassing immutable types, you need to override __new__;
otherwise you need to override __init__.
Here is an in-depth explanation: http://www.python.org/download/releases/2.2/descrintro/#metaclasses

Here is some code:

class MyTuple(tuple):
	def __new__(cls, names, values):
		for name, value in zip(names, values):
			setattr(cls, name, value)
		return tuple.__new__(cls, values)

class MyList(list):
	def __init__(self, names, values):
		list.__init__(self, values)
		for name, value in zip(names, values):
			setattr(self, name, value)

names = ['A', 'B', 'C']
values = ['a', 'b', 'c']

tup = MyTuple(names, values)
print tup
print tup[0]
print tup.B

lst = MyList(names, values)
print lst
print lst[0]
print lst.B


L.



More information about the Python-list mailing list