str method magic len dict __eq__ __add__ python

method - python__ repr__



TypeError después de anular el método__add__ (5)

Estoy tratando de entender cómo funciona __add__ :

class MyNum: def __init__(self,num): self.num=num def __add__(self,other): return MyNum(self.num+other.num) def __str__(self): return str(self.num)

Si los pongo en una lista

d=[MyNum(i) for i in range(10)]

esto funciona

t=MyNum(0) for n in d: t=t+n print t

Pero esto no:

print sum(d) TypeError: unsupported operand type(s) for +: ''int'' and ''instance''

¿Qué estoy haciendo mal? ¿Cómo puedo hacer que la suma () funcione?

ACTUALIZAR

Mi problema es cómo usar la suma en una lista de objetos que admiten el __add__ , necesito mantenerlo tan genérico como sea posible.


Me opongo a la retransmisión en suma () con un punto de inicio, el agujero del circuito expuesto a continuación,

In [51]: x = sum(d, MyNum(2)) In [52]: x.num Out[52]: 47

Preguntándose por qué obtuviste 47 mientras esperabas ... comienza desde 2nd de MyNum () saliendo primero y agrégalo hasta el final, por lo que el resultado esperado es = 44 (suma (rango (2,10))

La verdad aquí es que 2 no se guarda como objeto / posición inicial sino que se trata como una adición al resultado

suma (rango (10)) + 2

Uy, enlace roto !!!!!!

Usar radd

Aquí abajo el código correcto. También tenga en cuenta el siguiente

Python llama a __radd__ solo cuando el objeto en el lado derecho de + es tu instancia de clase, por ejemplo: 2 + obj1

#!/usr/bin/env python class MyNum: def __init__(self,num): self.num=num def __add__(self,other): return MyNum(self.num+other.num) def __radd__(self,other): return MyNum(self.num+other) def __str__(self): return str(self.num) d=[MyNum(i) for i in range(10)] print sum(d) ## Prints 45 d=[MyNum(i) for i in range(2, 10)] print sum(d) ## Prints 44 print sum(d,MyNum(2)) ## Prints 46 - adding 2 to the last value (44+2)


Necesitas definir __radd__ también para que esto funcione.

__radd__ es inverso agregar . Cuando Python intenta evaluar x + y , primero intenta llamar a x.__add__(y) . Si esto falla, regresa a y.__radd__(x) .

Esto le permite anular la suma solo tocando una clase. Considere por ejemplo cómo Python debería evaluar 0 + x . Se intenta una llamada a 0.__add__(x) pero int no sabe nada sobre su clase. No se puede cambiar el método __add__ en int , de ahí la necesidad de __radd__ . Supongo que es una forma de inversión de dependencia.

Como Steven señaló, la sum funciona en el lugar, pero comienza desde 0. Entonces, la primera adición es la única que debería usar __radd__ . ¡Como un buen ejercicio, puedes verificar que este sea el caso!


Otra opción es reducir (functools.reduce en Python 3.x).

from functools import reduce from operators import add d=[MyNum(i) for i in range(10)] my_sum = reduce(add,d)


>>> help(sum) Help on built-in function sum in module __builtin__: sum(...) sum(sequence[, start]) -> value Returns the sum of a sequence of numbers (NOT strings) plus the value of parameter ''start'' (which defaults to 0). When the sequence is empty, returns start.

En otras palabras, proporcione un valor de inicio:

sum(d, MyNum(0))

Edición pegada de mi comentario siguiente:

sum funciona con un valor de inicio predeterminado del entero cero. Su clase MyNum tal como está escrita no sabe cómo agregarse a enteros. Para resolver esto tienes dos opciones. O bien puede proporcionar un valor de inicio para sum que tenga el mismo tipo que su clase, o puede implementar __radd__ , que Python llama al agregar valores de diferentes tipos (como cuando el primer valor en d se agrega al valor de inicio predeterminado de cero).


class MyNum: def __init__(self,num): self.num=num def __add__(self,other): return self.num += other.num def __str__(self): return str(self.num) one = MyNum(1) two = MyNum(2) one + two print(two.num)