473,386 Members | 1,710 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

modifying __new__ of list subclass

Hi,

I'm been trying to create some custom classes derived from some of
python's built-in types, like int and list, etc. I've run into some
trouble, which I could explain with a couple simple examples. Lets say
I want an int-derived class that is initilized to one greater than what
it's constructor is given:

class myint(int):
def __new__(cls, intIn):
newint = int(intIn+1)
return int.__new__(cls, newint)

print myint(3), myint(10)
Okay, seems to do what I want. Now, lets say I want a list class that
creates a list of strings, but appends "_" to each element. I try the
same thing:
class mylist(list):
def __new__(cls, listIn):
newlist = list()
for i in listIn:
newlist.append(str(i) + "_")
print "newlist: ", newlist
return list.__new__(cls, newlist)

print mylist(("a","b","c"))

Doesn't seem to work, but that print statement shows that the newlist is
what I want... Maybe what I return from __new__ is overwritten in
__init__? Could someone enlighten me as to why - and why this is
different than the int case?

Thanks,
Ken
Aug 15 '06 #1
5 2134
Ken Schutte wrote:
I want an int-derived class that is initilized to one greater than what
it's constructor is given:

class myint(int):
def __new__(cls, intIn):
newint = int(intIn+1)
return int.__new__(cls, newint)
Or simply:

class myint(int):
def __new__(cls, int_in):
return int.__new__(cls, int_in + 1)
Now, lets say I want a list class that
creates a list of strings, but appends "_" to each element. I try the
same thing:

class mylist(list):
def __new__(cls, listIn):
newlist = list()
for i in listIn:
newlist.append(str(i) + "_")
print "newlist: ", newlist
return list.__new__(cls, newlist)
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__::

class mylist(list):
def __init__(self, list_in):
for item in list_in:
self.append(str(item) + '_')

STeve
Aug 15 '06 #2
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?

Thanks for the reply.

Aug 15 '06 #3
Ken Schutte <ks******@csail.mit.eduwrote:
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?
Wrong: the return value of __new__ is most definitely NOT "totally
ignored", since it's what gets passed as the first argument of __init__
(as long as it's an instance of the type in question). Easy to check
for yourself, e.g.:
>>class ha(list):
.... def __new__(cls, *a):
.... x = list.__new__(cls, *a)
.... x.foo = 23
.... return x
....
>>z = ha()
z.foo
23
>>>
as you can see, the "totally ignored" hypothesis is easily disproved.

Of course, there's no particular reason why class ha would _want_ to set
the .foo attribute in __new__ rather than __init__, so that doesn't yet
answer your other question about "is there a use". That answer is a
resounding "yes", but the uses may be subtler than you're considering:
for example, you may use the subtype as a general-purpose "factory", so
that instantiating the subtype may return objects that are not in fact
instances of the subtype (that bypasses the __init__ call); or, the
overriding of __new__ may go together with the overriding of __init__
(so that the latter doesn't blast the object's state) for such purposes
as singletons or more generally types with a finite "pool" of instances.
Alex

Aug 15 '06 #4
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
Aug 15 '06 #5
Steven Bethard wrote:
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__::
Okay, I see what's happening now. Steve and Alex - thanks for the great
explanations.

Ken
Aug 15 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Michele Simionato | last post by:
Let me show first how does it work for tuples: >>> class MyTuple(tuple): .... def __new__(cls,strng): # implicit conversion string of ints => tuple .... return...
3
by: H Jansen | last post by:
I try to work out how to use __new__ and metaclass (or __metaclass__) mechanisms in order to change the base class at runtime. I haven't been successful so far, however, even after also reading...
9
by: Felix Wiemann | last post by:
Sometimes (but not always) the __new__ method of one of my classes returns an *existing* instance of the class. However, when it does that, the __init__ method of the existing instance is called...
5
by: could ildg | last post by:
As there is already __init__, why need a __new__? What can __new__ give us while __init__ can't? In what situations we should use __new__? And in what situations we must use __new__? Can __new__...
1
by: s.lipnevich | last post by:
Hi All, Is anything wrong with the following code? class Superclass(object): def __new__(cls): # Questioning the statement below return super(Superclass, cls).__new__(Subclass) class...
18
by: Paulo da Silva | last post by:
Sorry to put here too many questions about __init__ __new__ stuff but I always found a new problem when using them. I have searched for simple __new__ docs on how to do the basic things but find...
5
by: Sandra-24 | last post by:
Ok here's the problem, I'm modifying a 3rd party library (boto) to have more specific exceptions. I want to change S3ResponseError into about 30 more specific errors. Preferably I want to do this...
4
by: Ethan Furman | last post by:
Emile van Sebille wrote: Good point. What I'm curious about, though, is the comment in the code about making the Decimal instance immutable. I was unable to find docs on that issue. ~Ethan~
3
by: macaronikazoo | last post by:
i'm having a hell of a time getting this to work. basically I want to be able to instantiate an object using either a list, or a string, but the class inherits from list. if the class is...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.