2012-05-23 14 views
8
#it's python 3.2.3 
class point: 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

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

    def __repr__(self): 
     return 'point(%s, %s)' % (self.x, self.y) 

class Test: 
    def __init__(self): 
     self.test1 = [point(0, i) for i in range(-1, -5, -1)] 
     self.test2 = [point(i, 0) for i in range(-1, -5, -1)] 

     print('%s\n+\n%s\n=\n%s' % (self.test1[0], self.test2[0], self.test1[0] + self.test2[0])) 

test = Test() 
input() 

La salida de este programa esmétodo de adición personalizada falla durante la interpolación de cadenas

point(-1, -1) 
+ 
point(-1, 0) 
= 
point(-1, -1) 

Pero debe ser

point(-1, -1) 
+ 
point(-1, 0) 
= 
point(-2, -1) 

Pero si lo hago

print(point(-1, -1) + point(-1, 0)) 

Funciona perfectamente

Quiero saber por qué y cómo solucionar este problema

p.s. lo siento si mi inglés es malo :)

Respuesta

17

Su función __add__ modifica el argumento de la izquierda a +. Por ejemplo:

>>> x = point(0, 0) 

>>> x + point(1, 1) 
point(1, 1) 

>>> x 
point(1, 1) 

debería cambiar __add__ ser como

def __add__(self, oth): 
    return point(self.x + oth.x, self.y + oth.y) 
+3

Nada como pegar código y tener a alguien más que vencer por unos segundos. Mi error claramente fue tomarse el tiempo de escribir "er" en "otro" ... ;-) – DSM

+1

Pero, el código de OP devuelve el objeto original, y de hecho funciona en otro contexto. No creo que esta sea una explicación suficiente. – Marcin

+1

Estoy de acuerdo con @Marcin, aunque este es el único problema obvio en el código OP, no puede ser toda la historia, solo los agrega una vez y no imprime el punto LH después de eso, solo antes. Los efectos secundarios no deberían ser notados por este caso de prueba en particular. A menos que los literales tuplas puedan ser evaluados fuera de orden? – lvc

3

Usted dice que la salida debe ser:

point(-1, -1) 
+ 
point(-1, 0) 
= 
point(-2, -1) 

en realidad debería ser:

point(0, -1) 
+ 
point(-1, 0) 
= 
point(-1, -1) 

porque estás creando ese primer punto con [point(0, i) for i in range(-1, -5, -1)] (tenga en cuenta que el parámetro x es 0).

Esto es una consecuencia de la evaluación de (self.test1[0], self.test2[0], self.test1[0] + self.test2[0])) - la adición modifica el primer punto en esa tupla (son el mismo objeto). Esta es también la razón por la cual su segundo ejemplo funciona correctamente (o parece): solo imprime el objeto modificado una vez.

La implementación de __add__ que proporciona es adecuada para __iadd__ para implementar el operador +=. Una aplicación correcta debería crear un nuevo objeto point:

def __add__(self, oth): 
    return point(self.x + oth.x, self.y + oth.y) 
+0

Sí, ahora lo sé – foxneSs

Cuestiones relacionadas