Dynamically creating variable/method/function names¶
Sometimes a programmer gets an idea to make his/her work easier by creating magically working code that uses setattr()
and getattr()
functions to set some variable. While this may look like a good idea, because there is no need to write all the methods by hand, you are asking for trouble down the road.
Example¶
Consider the following code. You have some data and want to update the class with all of the data. Of course you don’t want to do this by hand, especially if there are tons of items in data_dict
. However, when refactoring this kind of code after several years, and you’d like to know where some variable is added to this class, you’d usually use grep
or ack_grep
to find it. But when setting variables/methods/functions like this, you’re screwed.
data_dict = {'var1': 'Data1', 'var2': 'Data2'}
class MyAwesomeClass:
def __init__(self, data_dict):
for key, value in data_dict.iteritems():
setattr(self, key, value)
While previous example may look easy to find and debug, consider this:
data_list = ['dat1', 'dat2', 'dat3']
data_dict = {'dat1': [1, 2, 3],
'dat2': [4, 5, 6],
'dat3': [7, 8, 9],
'dat4': [0, 4, 6]}
class MyAwesomeClass:
def __init__(self, data_list, data_dict):
counter = 0
for key, value in data_dict.iteritems():
if key in data_list:
setattr(self, key, value)
else:
setattr(self, 'unknown' + str(counter), value)
counter += 1
Now the class contains also unknownX
variables indexed by their count. Well, what a nice mess we created here. Try to find a year later where these variables come from.
Solutions¶
Find another way¶
While the approach in the examples above may be the easiest to write, it is the worst to maintain later. You should always try to find another way to solve your problem.
Typical examples:
- Use function to parse incoming data
- Use the data dict/list itself without class
This however depends on the task at hand.