Dynamiczne definiowanie __add__ (i innych magicznych metod) [duplikat]

Nov 24 2020

Słyszałem, że to się a + brozszerza a.__add__(b). Jednak w moim kodzie tak to nie działa. Weź ten kod:

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

Kiedy próbuję TestAdd(5).__add__(1), zwraca 6 poprawnie. Kiedy próbuję TestAdd(5) + 1, pojawia się ten błąd:

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'

Dlaczego to? Czy coś mi brakuje?

Odpowiedzi

chepner Nov 24 2020 at 03:11

Metody magiczne nie są wyszukiwane w instancjach, ale w klasach. TestAdd(5) + 1jest dokładniej równoważne tmp = TestAdd(5); TestAdd.__add__(tmp, 1), a ty nie zdefiniowałeś TestAdd.__add__.

AKX Nov 24 2020 at 03:10

Nie możesz użyć __getattr__do dynamicznego zwrócenia magicznej metody; jest to szczegółowo udokumentowane w 3.3.10 Wyszukiwanie metod specjalnych w podręczniku.