2012-05-07 63 views
8

Recientemente me enteré sobre la sobrecarga del operador en python y me gustaría saber si lo siguiente es posible.Sobrecarga del operador en python con el objeto en el lado derecho del operador

Considere la siguiente clase hypothetica/artificiosa.

class My_Num(object): 
    def __init__(self, val): 
     self.val = val 
    def __add__(self, other_num): 
     if isinstance(other_num, My_Num): 
      return self.val + other_num.val 
     else: 
      return self.val + other_num 

sé que la forma en que está escrito arriba, puede hacer cosas como esta

n1 = My_Num(1) 
n2 = My_Num(2) 
n3 = 3 
print n1 + n2 
print n1 + n3 

y los que funcionará como se espera. También sé que la forma en que está escrito actualmente no puedo hacer esto

n1 = My_Num(1) 
n2 = 2 
print 2 + n1 

¿Hay alguna forma de esto? Sé que este ejemplo es artificial, pero tengo una aplicación en la que sería muy útil si, al sobrecargar al operador, la clase para la que defino el operador puede aparecer en el lado derecho del operador. ¿Es esto posible en Python?

Respuesta

9

Sí. Por ejemplo, está __radd__. Además, there are none para __le__(), __ge__(), etc., sino como Joel Cornett observa correctamente, si se define solamente __lt__, a > b llama a la función __lt__ de b, que proporciona una solución.

>>> class My_Num(object): 
...  def __init__(self, val): 
...   self.val = val 
...  def __radd__(self, other_num): 
...   if isinstance(other_num, My_Num): 
...    return self.val + other_num.val 
...   else: 
...    return self.val + other_num 
... 
>>> n1 = My_Num(1) 
>>> n2 = 3 
>>> 
>>> print n2 + n1 
4 
>>> print n1 + n2 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for +: 'My_Num' and 'int' 

Tenga en cuenta que al menos en algunos casos es razonable hacer algo como esto:

>>> class My_Num(object): 
...  def __init__(self, val): 
...   self.val = val 
...  def __add__(self, other_num): 
...   if isinstance(other_num, My_Num): 
...    return self.val + other_num.val 
...   else: 
...    return self.val + other_num 
...  __radd__ = __add__ 
+0

Gracias. ¿Es __radd__ el único que permite eso? Los operadores específicos que necesito sobrecargar para mi aplicación son los operadores >> y <<. ¿Acaso no he tenido suerte de querer hacer esto para esos operadores? – martega

+0

No. ¿Hiciste clic en el enlace? Hay '__rrshift__', y así sucesivamente. – senderle

+1

Es posible comparar directamente en cierta medida controlando qué operadores se definen para cada clase. Si A y B solo tienen definido __lt__, por ejemplo. A A llamará al método que pertenece al extremo pequeño. –

1

Tienes que sobrecargar el método __radd__ (además del lado derecho). Su función debe ser muy similar a su método __add__, por ejemplo:

def __radd__(self, other): 
    return self.val + other.val