[Tutor] use of __new__

spir denis.spir at free.fr
Fri Jun 12 15:48:13 CEST 2009


Le Fri, 12 Jun 2009 22:37:17 +1000,
Lie Ryan <lie.1296 at gmail.com> s'exprima ainsi:

> spir wrote:
> > Hello,
> > 
> > I have (again) some issue using __new__.
> > What I need is basically to catch an object creation and yield an object
> > of an alternate type, when a condition is met.
> > 
> > Basically, the outline looks like:
> > 
> > class Normal(object):
> >     def __new__(cls, arg):
> >         if cond(arg):
> >             # <yield instance of Special>
> >             # expression is simply: Special(arg)
> >             # must be __init__ialised !
> >         
> >         # Conceptually, nothing to change:
> >         # <yield instance of Normal>
> >         # must be __init__ialised !
> > 
> > But I got issues in both cases:
> > * cannot find how to get Special objects initialised
> > * cannot find how to return Normal object
> 
> roughly like this:
> 
> >>> class Special(object):
> ...     def __init__(self, arg):
> ...         self.arg = arg
> ...
> >>> class Normal(object):
> ...     def __new__(cls, arg):
> ...         if arg:
> ...             return Special(arg)
> ...         else:
> ...             ret = super(Normal, cls).__new__(cls)
> ...             ret.__init__(arg)
> ...             return ret
> ...     def __init__(self, arg):
> ...         self.arg = arg
> ...

Right, thank you. I continued my trials and ended with seemingly working code, close to yours.

		# case pattern is Klass: yield String instead
		if isinstance(pattern,Klass):
			self = String(pattern, numMin,numMax, expression,name)
#~ 			self.__init__(pattern, numMin,numMax, expression,name)
			return self
		# else a Repetition
		self = Pattern.__new__(cls,pattern, numMin,numMax, expression,name)
		return self

I have more questions:

1. For the 'normal' (second) case, I read in the docs that __new__ *must* return the new object. This should be done using the supertype's __new__. But you don't do it and it seems to work anyway. In this case, __init__ is (supposed to be) called automagically.

2. For the special case, as you can see the __init__ line is commented out and it works anyway. While the docs positively assert that __init__ *won't* be called if an object of a different type is returned, it is anyway.

Of course, i checked that init methods are really used in both cases.

So, how do things _actually_ work?
(Such confusions are why each time I need __new__ I have to re-learn the real way to use it.)

> >>> a = Normal(True)
> >>> b = Normal(False)
> >>> a.arg
> True
> >>> b.arg
> False
> >>>
> 
> generally though, avoid using __new__
> 
> 
> > (also Normal's supertype has no explicite __new__, but it has an __init__)
> 
> Haven't tested yet, but that should be no problem as python will use the
> supertype's supertype's __new__ and at the end of the method resolution
> order is object.__new__()

That's what I thought, too.
Thanks again,
Denis
------
la vita e estrany


More information about the Tutor mailing list