modifying __new__ of list subclass
Steven Bethard
steven.bethard at gmail.com
Tue Aug 15 12:30:56 EDT 2006
Ken Schutte wrote:
> Steven Bethard wrote:
>>
>> The __new__ method is for immutable types. So things like str and int
>> do their initialization in __new__. But for regular mutable types,
>> you should do your initialization in __init__::
>
> I see... So, is there a use for __new__ in mutable types? From my
> list-derirved class, it was obviously being called, but it's return
> value is totally ignored?
Not ignored, it's just having it's __init__ method called after your
__new__ method.
It might help for a moment to consider what happens when you call a
class object, e.g.::
c = C()
Just like any other object, when Python sees the ``()``, it looks for a
__call__ method on the object. Now classes are instances of the
``type`` type, which has a call method that looks something like::
def __call__(cls, *args, **kwargs):
result = cls.__new__(cls, *args, **kwargs)
if isinstance(result, cls):
result.__init__(*args, **kwargs)
return result
What's happening in your list case is that list.__init__ clears the list::
>>> l = [1, 2, 3]
>>> l.__init__()
>>> l
[]
So even though your __new__ method returns the object you want, the
__init__ method is clearing out all the items you've added and then
re-adding them as it normally would. To prove this to yourself, take a
look at what happens when we override __init__::
>>> class mylist(list):
... def __new__(cls, items):
... result = super(mylist, cls).__new__(cls)
... for item in items:
... result.append('%s_' % item)
... return result
...
>>> mylist([1, 2, 3])
[1, 2, 3]
>>> class mylist(list):
... def __new__(cls, items):
... result = super(mylist, cls).__new__(cls)
... for item in items:
... result.append('%s_' % item)
... return result
... def __init__(self, items):
... pass
...
>>> mylist([1, 2, 3])
['1_', '2_', '3_']
Of course, I've made __new__ work above, but the simpler solution is
just to override __init__ since that's where all the work's being done
anyway.
See Alex Martelli's response to answer your question "So, is there a use
for __new__ in mutable types?". You'd probably only want to override
__new__ if you were going to use the class as a factory to produce a
bunch of different types of objects.
STeVe
More information about the Python-list
mailing list