Subclassing complex with computed arguments

Kent Johnson kent3737 at yahoo.com
Fri Nov 26 00:06:59 EST 2004


Jp Calderone wrote:
> On 25 Nov 2004 14:30:18 -0800, pcolsen at comcast.net (Peter Olsen) wrote:
> 
>>I want to define a class "point" as a subclass of complex.  
>>
>>When I create an instance 
>>
>>sample = point(<arglist>) 
>>
>>I want "sample" to "be" a complex number, but with its real and
>>imaginary parts computed in point()'s __init__ function with their
>>values based on the arglist.  I want to compute with point instances
>>as though they were native complex numbers, but I want to be able to
>>define some new methods and over-ride some of complex's existing ones.
> 
>   Something like this?
> 
>>>>class simple(complex):
> 
> ...     def __new__(cls, real=0, imag=0):
> ...             return super(simple, cls).__new__(cls, real + 1, imag + 1)
> ...

Unfortunately operations on 'simple' objects will return 'complex' 
results. This is probably not what the OP wants.

 >>> class point(complex):
...   def __new__(cls, x, y):
...     return complex.__new__(point, x*2, y*2)
...
 >>> p=point(1,2)
 >>> p
(2+4j)
 >>> type(p)
<class '__main__.point'>
 >>> p2=p+1
 >>> p2
(3+4j)
 >>> type(p2)
<type 'complex'>

I don't know if there is an easy way around this. A brute force approach 
might be to override __add__(), etc to return point objects instead of 
complex - though I haven't been able to figure out how to do this. I tried:
     def __add__(self, *args, **kwds):
         val = complex.__add__(self, *args, **kwds)
         return point(val)

but val is NotImplemented instead of the desired sum ??

I had more luck with a delegation-based approach:

class point(object):
     def __init__(self, *args, **kwds):
         if len(args) == 1 and isinstance(args[0], complex):
             self.c = args[0]
         if len(args) == 2:
             self.c = complex(args[0]*2, args[1]*2)
         else:
             self.c = complex(*args, **kwds)

     def __add__(self, y):
         val = self.c+y
         return point(val)

     def __repr__(self):
         return 'point' + self.c.__repr__()


p=point(1,2)
print p
p1 = p+1
print p1

prints:
point(2+4j)
point(3+4j)

I was hoping that the special methods of point could delegate to the 
corresponding special method of complex, so the delegation could be 
automated, but again I couldn't get this to work. Maybe someone else can 
explain this? For example if c is a complex number, why does 
c.__add__(1) return NotImplemented?

I tried adding a delegating __coerce__() to class point but it is never 
called...

Call me confused...
Kent

> 
>>>>simple(3, 4)
> 
> (4+5j)
> 
> 
>   The trick is that since complex instances are immutable, you need to change the initialization parameters before the instance is ever created.  __new__ is the hook for that.
> 
>   Jp



More information about the Python-list mailing list