I've been stuck with this problem in python for some time now: I need to create a list of methods inside a class that do almost the same thing but with different instance member variables. So my first attempt is something like this:
from functools import partial
class Operations:
def __init__(self):
self.a = 10
self.b = 20
self.c = 30
self.add_operation_1 = partial(self.generic_add_1, 'a', 'b')
self.add_operation_2 = partial(self.generic_add_1, 'a', 'c')
def generic_add_1(self, first, second):
first_value = getattr(self, first)
second_value = getattr(self, second)
setattr(self, first, first_value + second_value)
instance = Operations()
instance.add_operation_1()
print(instance.a)
# Should print 30
instance.add_operation_2()
print(instance.a)
# Should print 60
As you can see I use getattr and setattr to reference the attributes I need to change.
This works, but is really slow because partial only keeps the parameters and when the function is called, it passes them to the original function. Also, i'm not sure about this, but aren't getattr and setattr a bit slower than using something like object.property
So i managed to get a second attempt:
class Operations:
def __init__(self):
self.a = 10
self.b = 20
self.c = 30
self.add_operation_1 = self.generic_add('a', 'b')
self.add_operation_2 = self.generic_add('a', 'c')
def generic_add(self, first, second):
first_value = getattr(self, first)
second_value = getattr(self, second)
def real_operation():
setattr(self, first, first_value + second_value)
return real_operation
instance = Operations()
instance.add_operation_1()
print(instance.a)
# Should print 30
instance.add_operation_2()
print(instance.a)
# Should print 60 but returns 40 instead!!!
This time i didn't use partials but a closure instead.
The main advantage is that getattr is only executed once when create the instance object and not when calling the methods, but I can't find a way to get rid of setattr.
And as a side effect this doesn't work as I expected. getattr gets the value of the property at the beginning, so any changes to those properties won't be seen by the returned functions.
So now i'm kind of stuck. Is there a way to generate a method like this:
def expected_function(self):
self.a = self.a + self.b
given the properties names?
Thanks.