I have a class where I want to initialize an attribute self.listN
and an add_to_listN
method for each element of a list, e.g. from attrs = ['list1', 'list2']
I want list1
and list2
to be initialized as empty lists and the methods add_to_list1
and add_to_list2
to be created. Each add_to_listN
method should take two parameters, say value
and unit
, and append a tuple (value, unit)
to the corresponding listN
.
The class should therefore look like this in the end:
class Foo():
def __init__(self):
self.list1 = []
self.list1 = []
def add_to_list1(value, unit):
self.list1.append((value, unit))
def add_to_list2(value, unit):
self.list2.append((value, unit))
Leaving aside all the checks and the rest of the class, I came up with this:
class Foo():
def __init__(self):
for attr in ['list1', 'list2']:
setattr(self, attr, [])
setattr(self, 'add_to_%s' % attr, self._simple_add(attr))
def _simple_add(self, attr):
def method(value, unit=None):
getattr(self, attr).append((value, unit))
return method
I also checked other solutions such as the ones suggested here and I would like to do it "right", so my questions are:
classmethod
s or not?__init__
, and in this case is there an alternative?for
loop and add these methods? Within the class definition? Out of it?Update
Although Benjamin Hodgson makes some good points, I'm not asking for a (perhaps better) alternative way to do this but for the best way to use the tools that I mentioned. I'm using a simplified example in order not to focus on the details.
To further clarify my questions: the add_to_listN
methods are meant to be additional, not to replace setters/getters (so I still want to be able to do l1 = f.list1
and f.list1 = []
with f = Foo()
).
The __add__() method in Python specifies what happens when you call + on two objects. When you call obj1 + obj2, you are essentially calling obj1. __add__(obj2). For example, let's call + on two int objects: n1 = 10.
You are making a design error. You could override __getattr__
, parse the attribute name, and return a closure which does what you want, but it's strange to dynamically generate methods, and strange code is bad code. There are often situations where you need to do it, but this is not one of them.
Instead of generating n
methods which each do the same thing to one of n
objects, why not just write one method which is parameterised by n
? Something roughly like this:
class Foo:
def __init__(self):
self.lists = [
[],
[]
]
def add(self, row, value):
self.lists[row].append(value)
Then foo.add1(x)
becomes simply foo.add(1, x)
; foo.add2(x)
becomes foo.add(2, x)
, and so on. There's one method, parameterised along the axis of variation, which serves all cases - rather than a litany of ad-hoc generated methods. It's much simpler.
Don't mix up the data in your system with the names of the data in your system.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With