Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

204
Vistas
Overloading operators using __getattr__ in Python

I am trying to overload several operators at once using the __getattr__ function. In my code, if I call foo.__add__(other) it works as expected, but when I try foo + bar, it does not. Here is a minimal example:

class Foo():
    
    
    def add(self, other):
        return 1 + other
    
    def sub(self, other):
        return 1 - other
    
    def __getattr__(self, name):
                
        stripped = name.strip('_')
        if stripped in {'sub', 'add'}:
            return getattr(self, stripped)
        else:
            return
    
if __name__=='__main__':
    
    bar = Foo()
    
    print(bar.__add__(1)) # works
    print(bar + 1) # doesn't work

I realize that it would be easier in this example to just define __add__ and __sub__, but that is not an option in my case.

Also, as a small side question, if I replace the line:

if stripped in {'sub', 'add'}:

with

if hasattr(self, name):

the code works, but then my iPython kernel crashes. Why does this happen and how could I prevent it?

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

This is happening because python operators use an optimization to look up the function implementing the operator. The following lines are roughly equivalent:

foo + 1
type(foo).__add__(foo, 1)

Operators are found specifically on the class object only, never on the instance.

bar.__add__(1) calls __getattr__ to find the missing attribute on bar. This works because it bypasses normal operator lookup procedures.

bar + 1 calls Foo.__add__(bar, 1) followed by int.__radd(1, bar). The first attribute lookup fails, and the second option raises TypeError.

over 4 years ago · Santiago Trujillo Denunciar

0

Also, as a small side question, if I replace the line: [...]

hasattr calls __getattr__ under the hood. Which explains what you saw when doing if hasattr(self, name):, you actually enter an infinite recursion since you have overwritten __getattr__.

See for yourself

class O:
    def __getattr__(self, attr):
        print('yooo')
        return super().__getattr__(attr)
        #      self.__getattr__(attr) -> RecursionError
>>> hasattr(O(), 'ya')
yooo
False
over 4 years ago · Santiago Trujillo Denunciar

0

I've found a semi-satisfying work-around that does not involve meta-classes:

class Foo():
    
    def add(self, other):
        return 1 + other
    
    def sub(self, other):
        return 1 - other

# Add operators to the type object
def get_operator(name):
    return getattr(Foo, name.strip('_'))

for op in ['__add__', '__sub__']:
    setattr(Foo, op, get_operator(op))

    
if __name__=='__main__':
    
    bar = Foo()
    
    print(bar + 2)
    print(bar - 2)
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda