python bug when subclassing list?

Arnaud Delobelle arnodel at googlemail.com
Thu Nov 6 21:05:52 CET 2008


Hamish McKenzie <hamish at valvesoftware.com> writes:

> I want to write a Vector class and it makes the most sense to just
> subclass list.  I also want to be able to instantiate a vector using
> either:
>
> Vector( 1, 2, 3 )
> OR
> Vector( [1, 2, 3] )
>
>
> so I have this:
>
> class Vector(list):
>         def __new__( cls, *a ):
>                 try:
>                         print a
>                         return list.__new__(cls, a)
>                 except:
>                         print 'broken'
>                         return list.__new__(cls, list(a))
>
>
> doing Vector( 1, 2, 3 ) on this class results in a TypeError - which
> doesn't seem to get caught by the try block (ie "broken" never gets
> printed, and it never tries to
>
> I can do pretty much the exact same code but inheriting from tuple
> instead of list and it works fine.
>
> is this a python bug?  or am I doing something wrong?

You're doing something wrong!

When you call Vector.__new__(cls, *a), this creates a new list object
(call it L) and then calls Vector.__init__(L, *a) automatically, falling
back to list.__init__(L, *a) (which won't work when a has more than one
element).  In fact list initialisation is done in list.__init__, not in
list.__new__ (as opposed to tuple initialisation because tuples are
immutable).

A solution:

>>> class Vector(list):
...     def __init__(self, *args):
...         try:
...             list.__init__(self, *args)
...         except TypeError:
...             list.__init__(self, args)
... 
>>> Vector([1,2,3])
[1, 2, 3]
>>> Vector(1,2,3)
[1, 2, 3]
>>> Vector(1)
[1]
>>> Vector()
[]

HTH

-- 
Arnaud



More information about the Python-list mailing list