I'm looking into generating a Python class dynamically from data. (The purpose is to let users specify some software tests in a simple file, without knowing any Python). I have run into an effect I did not expect; as a toy example to quickly check that I can create methods according to a naming scheme I did the following:
import unittest
attrdict = {}
for i in range(3):
attrdict["test%s"%i]= types.MethodType(lambda self: i)
attrdict["runTest"]=lambda self: [eval("self.test%s()"%i) for i in range(3)]
dynTC = type('dynTC', (unittest.TestCase,), attrdict )
now when I execute
dynTC().runTest()
... I would expect
[0,1,2]
as output, but the actual result is
[2,2,2]
I would expect the lambda definitions to bind a deep copy of the loop index, since it is just a number rather than a more complex structure, but clearly there's stuff going on here that I don't understand.
I have a feeling this may be a common 'gotcha' for new Python programmers, but all the terms I can think of to describe the problem are so generic that my searches only return a deluge of unrelated answers.
Could you please explain to me what is happening here instead of what I expected, and preferably also what I should have done to create the desired effect of several /different/ methods.