Is __mul__ sufficient for operator '*'?

Gary Herron gherron at islandtraining.com
Mon Oct 19 21:01:40 EDT 2009


Muhammad Alkarouri wrote:
> Hi everyone,
>
> I was having a go at a simple implementation of Maybe in Python when I
> stumbled on a case where x.__mul__(y) is defined while x*y is not.
>
> The class defining x is:
>
> class Maybe(object):
>     def __init__(self, obj):
>         self.o = obj
>     def __repr__(self):
>         return 'Maybe(%s)' % object.__getattribute__(self, "o")
>     def __getattribute__(self, name):
>         try:
>             o = object.__getattribute__(self, "o")
>             r = getattr(o,name)
>             if callable(r):
>                 f = lambda *x:Maybe(r(*x))
>                 return f
>             else:
>                 return Maybe(r)
>         except:
>             return Maybe(None)
>
> The code exercising this class is:
>
>   
>>>> x=Maybe(9)
>>>> x.__mul__(7)
>>>>         
> Maybe(63)
>   
>>>> x*7
>>>>         
>
> Traceback (most recent call last):
>   File "<pyshell#83>", line 1, in <module>
>     x*7
> TypeError: unsupported operand type(s) for *: 'Maybe' and 'int'
>   

The product 7*x will execute __mul__, but to catch x*7, you need to 
define __rmul__ (the 'r' stands for reverse or some such). 

However, in fact, you have *not* defined __mul__ in your class.  Your 
__getattribute__ is catching __mul__ as an undefined reference, and 
doing something with it -- not sure what though.

As proof, continue testing:   x.__mul__ and x.__rmul__ both return 
values (lambdas defined within __getattribute__) and neither x*7 or 7*x 
work.

If you want both x* and 7*x to be defined, try
    def __mul__(self,r):
        ...
    def __rmul__(self,r):
       ....

Or the operation is commutative, perhaps you can get away with reusing 
__mul__ for both.
    def __mul__(self,r):
        ...
    __rmul__ = __mull__


Gary Herron


> The farthest I can go in this is that I presume that __mul__ (as
> called by operator *) is supposed to be a bound method while I am
> returning a lambda function. Is this correct? And How can I make the
> implementation support such operators?
>
> Cheers,
>
> Muhammad Alkarouri
>   




More information about the Python-list mailing list