2011-08-20 20 views
19

Escribí una clase para representar vectores en Python (como un ejercicio) y estoy teniendo problemas para extender los operadores incorporados.El método __mul__ definido por el usuario no es conmutativo

Definí un método __mul__ para la clase vectorial. El problema es que en la expresión x * y el intérprete llama al método __mul__ de x, no y.

Así vector(1, 2, 3) * 2 devuelve un vector < 2, 4, 6> justo como debería; pero 2 * vector(1, 2, 3) crea un TypeError porque la clase int incorporada no es compatible con la multiplicación por mis vectores definidos por el usuario.

que podría resolver este problema simplemente escribiendo una nueva función de multiplicación

def multiply(a, b): 
    try: 
     return a * b 
    except TypeError: 
     return b * a 

pero esto requeriría la redefinición de cada función que quiero usar con mis clases definidas por el usuario.

¿Hay alguna manera de hacer que la función incorporada maneje esto correctamente?

Respuesta

24

Si desea la conmutatividad para los diferentes tipos debe implementar __rmul__(). Si se implementa, se llama, como todos los métodos especiales __r*__(), si la operación de lo contrario aumentaría un TypeError. Tenga en cuenta que los argumentos se intercambian:

class Foo(object): 
    def __mul_(self, other): 
     ''' multiply self with other, e.g. Foo() * 7 ''' 
    def __rmul__(self, other): 
     ''' multiply other with self, e.g. 7 * Foo() ''' 
+0

¿Cómo sabe Python para invocar 'rmul__' Foo .__ y no el' __mul__' del otro objeto? –

+2

Intenta usar el '__mul__' del lado izquierdo, y si no puede encontrarlo, busca el' __rmul__' del lado derecho. –

+3

@pst, Python llama a '__mul__' primero, pero si no existe o si devuelve' NotImplemented', Python llama a '__rmul__' del otro objeto. (Tenga en cuenta que si '__mul__' genera una excepción,' __rmul__' no se llama __not__. –

Cuestiones relacionadas