unine...@gmail.com writes: > class Person: > def __init__(self): > for prop in props: > setattr(self, "__" + prop[0], prop[1]) > setattr(Person, "Get" + prop[0], lambda self: getattr > (self, "__" + prop[0]))
[...] > The attributes are right, but the getter are not working. The problem > is that the lambda function always execute the last parameter passed > for all instances of the methods. How could it be done the right way? Ahh! Binding-versus-assignment confusion! Things to realise: * There are two mappings of interest when dealing with variables. The `binding' of a name maps the name to a variable. The variable stores a (reference to a) value. * Assignment stores a new (reference to a) value in the variable. * Binding modifies the mapping between names and variables. * Nested functions, as constructed by `lambda' or `def', inherit (we say `close over') the bindings visible in their surroundings. * Python's `for' loop works by assignment. So, what happens is this. In `__init__', there's a binding of the name `prop' to a variable. The `for' loop modifies this variable on each iteration, making it refer to successive elements of the `props' list. The `lambda's you create inherit the binding of `prop' from the surrounding `__init__', so the `lambda' sees the same variable as is being modified by the loop. Result: when you actually come to invoke one of the `lambda's -- after `__init__' finishes -- you find that its notion of `prop' is whatever the `for' left it as. To fix the problem, you need to make a separate variable for each iteration through the loop, and have the `lambda' close over that. Function parameters are the easy approach to making fresh variables with given contents: so we just call a function which accepts, and stores in a parameter, the value we want the `lambda' to see, and closes over the parameter. class Person (object): # use new-style classes def __init__(self): # allow parametrization def getter(propname): # close over new variable return lambda self: getattr(self, propname) for name, value in props: # destructuring wins setattr(self, '__' + name, value) for name, value in props: # only need to do this once setattr(Person, 'Get' + name, getter('__' + name)) Does that make sense? -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list