2001 Enchancement Wishlist

Pearu Peterson pearu at cens.ioc.ee
Sat Dec 30 03:52:10 EST 2000


On Fri, 29 Dec 2000, Raymond Hettinger wrote:

> 3.  __init__ is the only special method that doesn't allow a return value.
>    I think it should continue to return the new object by default but also
>    allow another return item to be substituted.  For example:
> 
>             def __init__( self ):
>                    if MyClass.aSingleton == None:
>                          MyClass.aSingleton = self
>                    return MyClass.aSingleton

I see that many Python experts are against this proposal but anyway, I
would like to support this idea with the following examples.

Say, I would like to define

class Real:
    def __init__(self,num):
        self.num = num
    <other number class methods>

class Complex:
    def __init__(self,real,imag):
        if imag == 0:
            return Real(real)
        self.real,self.imag = real,imag
    <other number class methods> 

That is, if imaginary part of a Complex number is zero, it's constructor
would return Real instance:

>>> a = Complex(1,2)
>>> b = Complex(1,0)
>>> print a.__class__.__name__,b.__class__.__name__
Complex Real

Yes, I could cover this example in Python 2.0 by defining:

class Complex:
    def __init__(self,real,imag):
        if imag == 0:
            self.__class__ = Real
            self.real = real
        else:
            self.real,self.imag = real,imag
    <other number class methods>

but it works only if __init__ should "return" a class instance.

For example, the following behavior cannot be handled in Python 2.0:

class NonZeroInteger:
    def __init__(self,num):
        if num == 0:
            return 0
        self.num = num
    <other number class methods>

so that
>>> type(NonZeroInteger(2)),type(NonZeroInteger(0))
(<type 'instance'>, <type 'int'>)

Sure, one can write wrapper functions (as some of you already suggested):

class _Complex:
    ...
def Complex(real,imag):
    if imag == 0: return Real(real)
    return _Complex(real,imag)

but I think that this way is actually a very unpythonic one,
especially if there is much simpler/cleaner solution available (that is,
possible), that is, allowing __init__ return arbitrary object.

I have used these number classes only for demonstration, but there are 
real situations where 'rich' __init__ would be very useful. For example,
in PySymbolic there are classes Plus, Symbol, etc and gmpy numbers that
are objects. E.g. class Plus represents a sum of its elements (arguments):

c = Plus(a,b,c)       -> c = a + b + c  # c is Plus instance

where a,b,c are Symbol instances.
Now, if one constructs a Plus instance only with one argument, 

c = Plus(a)           -> c = a          # c is Symbol instance

***lots of code*** could be avoided with rich Plus.__init__ that would
return in this case Symbol instance a.
If the argument to Plus constructor is gmpy number:

c = Plus(mpz(3))      -> c = mpz(3)     # c is mpz type object

then rich Plus.__init__ would return mpz object.

So, in my humble opinion, rich __init__ would be very useful feature.

	Pearu




More information about the Python-list mailing list