Definir __add__ (y otros métodos mágicos) dinámicamente [duplicar]

Nov 24 2020

Escuché que eso se a + bexpande a a.__add__(b). Sin embargo, no funciona así en mi código. Toma este código:

class TestAdd:
    def __init__(self, a):
        self.a = a
    def __getattr__(self, name):
        if name == '__add__':
            return (lambda y: self.a + y)

Cuando lo intento TestAdd(5).__add__(1), devuelve 6 correctamente. Cuando lo intento TestAdd(5) + 1, surge este error:

TypeError                                 Traceback (most recent call last)
<ipython-input-3-1c04c7082b89> in <module>
----> 1 TestAdd(5) + 1

TypeError: unsupported operand type(s) for +: 'TestAdd' and 'int'

¿Por qué es esto? ¿Me estoy perdiendo de algo?

Respuestas

chepner Nov 24 2020 at 03:11

Los métodos mágicos no se buscan en instancias, sino en clases. TestAdd(5) + 1es más exactamente equivalente a tmp = TestAdd(5); TestAdd.__add__(tmp, 1), y no lo ha definido TestAdd.__add__.

AKX Nov 24 2020 at 03:10

No se puede utilizar __getattr__para devolver dinámicamente un método mágico; esto se documenta en profundidad en 3.3.10 Búsqueda de métodos especiales en el manual.