python - overloading several operators at once
Question: I have a custom class and I want to overload several artihmetic operators, and
wonder if there is a way to avoid having to write out the code for each one
individually. I haven't been able to find any examples that don't explicity
overload each operator one-by-one.

    
    
    class Foo(object):
        a=0 
    
        def __init__(self, a):
            self.a=a            
    
        def __add__(self, other):
            #common logic here
            return Foo(self.a+other.a)
    
        def __sub__(self, other):
            #common logic here  
            return Foo(self.a-other.a)
    
        def __mul__(self, other):
            #common logic here
            return Foo(self.a*other.a)
    
    #etc...
    

The logic is slightly more complex than this, but the common pattern is that
each operator overload method contains some identical code to check that the
operation is allowed, and then constructs an operation using the class
members. I want to reduce the redundant code. This works:

    
    
    class Foo(object):
        a=0 
    
        def __init__(self, a):
            self.a=a            
    
        def operate(self, other, operator):
            #common logic here
            a = constructOperation(self.a, other.a, operator)
            return Foo(a)
    
        def __add__(self, other):
            return self.operate(other, "+")
    
        def __sub__(self, other):       
            return self.operate(other, "-")     
    
    
    def constructOperation(operand0, operand1, operator):
        if operator=="+": 
            return operand0 + operand1
        if operator=="-": 
            return operand0 - operand1
    

But it seems kind of silly to be constructing operations manually like that.
Does this approach make sense, or is there a better way here?


Answer: You can do it via reflection and higher order functions, though this may not
play well with inheritance.

    
    
    import operator
    
    def apply_a(func):
        def inner(self, other):
            return Foo(func(self.a, other.a))
        return inner
    
    class Foo(object):
        def __init__(self, a=0):
            self.a = a
    
    for name in ['__add__','__mul__','__sub__']:
        setattr(Foo, name, apply_a(getattr(operator, name)))
    

