Re: Dynamic methods and lambda functions
On Jan 28, 11:32 pm, Gabriel Genellina gagsl-...@yahoo.com.ar wrote: En Wed, 28 Jan 2009 16:05:39 -0200, coutinhoti...@gmail.com coutinhoti...@gmail.com escribió: I had the same problem myself. Mark's detailed explanation really helped me understand. I ended up doing something like: The code doesn't work as-is, could you please post a working version? Just for the record, so people reading this thread later don't get confused. -- Gabriel Genellina Sure! This works for me: class A: def __init__(self): names = 'n1', 'n2' for n in names: setattr(self, get%s % n, self._createGetter(n)) def _createGetter(self, n): def f(): return n return f if __name__ == __main__: a=A() print a.getn1() print a.getn2() -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
Hi! I had the same problem myself. Mark's detailed explanation really helped me understand. I ended up doing something like: class A: def __init__(self): names = 'n1', 'n2' for n in names: setattr(self, get%s % n, self._createGetter(n)) def _createGetter(self, n): def f(): return n return f Thanks a lot Cheers, Tiago -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
En Wed, 28 Jan 2009 16:05:39 -0200, coutinhoti...@gmail.com coutinhoti...@gmail.com escribió: I had the same problem myself. Mark's detailed explanation really helped me understand. I ended up doing something like: The code doesn't work as-is, could you please post a working version? Just for the record, so people reading this thread later don't get confused. -- Gabriel Genellina -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
Michael Torrie torr...@gmail.com writes: Basically, don't use a lambda. Create a real, local closure with a nested def block. That way the closure is created every time the parent function is called. Nope. I explained the real problem quite clearly, and it's to do with the difference between binding and assignment. What's the difference between these two pieces of code? ## First def __init__(self): for n, v in props: setattr(Person, '_' + n, v) setattr(Person, n, lambda self: getattr(self, '_' + n)) ## Second def __init__(self): for n, v in props: setattr(Person, '_' + n, v) def hack(self): return getattr(self, '_' + n) setattr(Person, n, hack) Lambda expressions are only ever compiled once during execution. The same is true of `def' bodies. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
Mark Wooding wrote: unine...@gmail.com writes: [...] * Assignment stores a new (reference to a) value in the variable. * Binding modifies the mapping between names and variables. I realise I have omitted what was doubtless intended to be explanatory detail, but I am having trouble reconciling those sentences. Would you mind explaining in vacuuo what you see as the difference between assignment and binding? regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
On 26 Jan., 15:13, Steve Holden st...@holdenweb.com wrote: Mark Wooding wrote: unine...@gmail.com writes: [...] * Assignment stores a new (reference to a) value in the variable. * Binding modifies the mapping between names and variables. I realise I have omitted what was doubtless intended to be explanatory detail, but I am having trouble reconciling those sentences. Would you mind explaining in vacuuo what you see as the difference between assignment and binding? regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ Assignment is binding values to names whereas binding is binding names to scopes. Marks terminology is a bit more standard than Pythons in this respect. As you know, Python avoids the idea of variables as if those were storage cells having a fixed logical address. -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
Steve Holden st...@holdenweb.com writes: Mark Wooding wrote: * Assignment stores a new (reference to a) value in the variable. * Binding modifies the mapping between names and variables. I realise I have omitted what was doubtless intended to be explanatory detail, but I am having trouble reconciling those sentences. Would you mind explaining in vacuuo what you see as the difference between assignment and binding? OK. This turned into something of an essay. I hope that it's of use to somebody... A name is a kind of expression. Expressions can be evaluated to yield values. Therefore, a name can be evaluated to yield a value. How does this happen? There are two distinct mappings involved. The first mapping is from names to variables. This mapping is usually called the `environment', and is acted upon by `binding'. The extent of the program text whose meaning is affected by a binding is called the `scope' of the binding[1]. In Python, the scope can be determined statically by analysing the program text (`lexical scope'). In some languages the scope can only be determined at run time (`dynamic scope'); other languages have a mixture of the two. Binding in Python is done in two ways: * /Explicit/ binding is done by `def' or `lambda': the parameters are bound, and the scope of the bindings is the entire function body (i.e., it does not include the default arguments). * /Implicit/ binding may be performed when a name as a result of an assignment operation -- either an assignment statement or one of a number of features which work by assignment, including `for' loops, list comprehensions, and `def' blocks. The scope of the binding in this case depends on the nature of the block in which the binding occurs: within `def' and `lambda'[2], the scope is the entire function body; within `class' and module toplevels, the scope is from the first-executed assignment to the end of the block. In all cases, names are bound to fresh variables when the scope of the binding begins. The environment within a binding block is formed by extending the environment of the surrounding program text. In the case of function definitions, in particular, we say that the function `closes over' the environment in which it is defined. The second mapping is from variables to values. This mapping doesn't seem to have a common name, though it's referred to as the `store' in some formal semantics (e.g., R5RS Scheme). The store is acted upon by assignment (and assignment-like operations such as `for' loops and list comprehensions). An assignment NAME = VALUE alters the store as follows: the variable bound to NAME becomes mapped to the result of evaluating VALUE. We can now consider some example programs. In [23]: def simple(x): : def inner(): : return x : return inner : When the function is invoked, say by In [24]: simple('boo!')() the name x is bound to a new variable, and the variable is assigned the value `boo!'. The body of `simple' is then executed. First, a function `inner' is defined: `def' is an assignment-like operation, which causes `inner' to be implicitly bound to a fresh variable on entry to the function. When the `def' is executed, that variable is assigned the value of a function. Finally, we return the result of evaluating `inner', i.e., the function we just constructed. The next pair of parentheses invoke the function `inner'. That function was defined within an environment in which x was bound to a variable that had been assigned the value 'boo!'. It therefore returns this value: Out[24]: 'boo!' Next example: In [26]: def mutant(x): : def inner(): : return x : x = 'changed!' : return inner : Suppose we invoke this one as In [27]: mutant('same')() The first steps are the same: x is bound to a fresh variable which is assigned the value 'same'; `inner' is bound to a fresh variable which is assigned a function value. Now the line `x = 'changed!'' is executed. This assigns the string 'changed!' to the variable bound to x. Finally, we return the function value. That function is now invoked. It was defined in an environment where x was bound to a variable whose last assigned value was 'changed!'. Therefore: Out[27]: 'changed!' The original poster's question can be illustrated by this example: In [28]: def problem(): : return [lambda: i for i in xrange(3)] : In [29]: [f() for f in problem()] This is actually the same as the mutant example in disguise. There is no parameter to bind, but `for' in a list comprehension is an assignment operation, and therefore i is implicitly bound when `problem' is invoked. The list comprehension performs three iterations. On each iteration,
Re: Dynamic methods and lambda functions
Mark Wooding wrote: Steve Holden st...@holdenweb.com writes: Mark Wooding wrote: * Assignment stores a new (reference to a) value in the variable. * Binding modifies the mapping between names and variables. I realise I have omitted what was doubtless intended to be explanatory detail, but I am having trouble reconciling those sentences. Would you mind explaining in vacuuo what you see as the difference between assignment and binding? OK. This turned into something of an essay. I hope that it's of use to somebody... A name is a kind of expression. Expressions can be evaluated to yield values. Therefore, a name can be evaluated to yield a value. How does this happen? There are two distinct mappings involved. The first mapping is from names to variables. This mapping is usually called the `environment', and is acted upon by `binding'. The extent of the program text whose meaning is affected by a binding is called the `scope' of the binding[1]. In Python, the scope can be determined statically by analysing the program text (`lexical scope'). In some languages the scope can only be determined at run time (`dynamic scope'); other languages have a mixture of the two. Yes. Kay Schleur pointed out that my confusion was due to too close a mental proximity to the Python term binding value to names for assignment. Once I realised you were using bindingto refer to the scope of names it all made much more sense. [...] Chapter 3 of the Structure and Interpretation of Computer Programs, by Abelson and Sussman explains this stuff in a more discursive and approachable manner. If you're still confused by my explanation (and by nature I tend to err on the side of precision rather than clarity, a fault which I know impairs my teaching ability), you may find theirs more useful: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-19.html#%_chap_3 Nonetheless, I hope that this description has been of some use. I found your precision most helpful, and the entire post was readable and useful. Thanks. regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
On 23 Jan., 13:28, unine...@gmail.com wrote: Hi, I want to add some properties dynamically to a class, and then add the corresponding getter methods. Something resulting in this: class Person: def Getname(self): return self.__name def Getage(self): return self.__age I've implemented the next code, creating the properties from a list: props = [ (name, peter), (age, 31), (wife, mary) ] 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])) if __name__ == __main__: person = Person() print person.__name print person.__age print person.__wife print print person.Getname() print person.Getage() print person.Getwife() And the resulting execution of this program is: peter 31 mary mary mary mary 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? Thanks in advance The standard trick is to de-closure the lambda using a keyword argument. So instead of writing lambda self: getattr(self, __ + prop[0])) you might write lambda self, prop = prop: getattr(self, __ + prop[0])) Now prop is local to the lambda and the lambda doesn't look up prop in the enclosing environment which certainly stores its last value. -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
unine...@gmail.com wrote: 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? Basically, don't use a lambda. Create a real, local closure with a nested def block. That way the closure is created every time the parent function is called. Lambda expressions are only ever compiled once during execution. -- http://mail.python.org/mailman/listinfo/python-list
Dynamic methods and lambda functions
Hi, I want to add some properties dynamically to a class, and then add the corresponding getter methods. Something resulting in this: class Person: def Getname(self): return self.__name def Getage(self): return self.__age I've implemented the next code, creating the properties from a list: props = [ (name, peter), (age, 31), (wife, mary) ] 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])) if __name__ == __main__: person = Person() print person.__name print person.__age print person.__wife print print person.Getname() print person.Getage() print person.Getwife() And the resulting execution of this program is: peter 31 mary mary mary mary 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? Thanks in advance -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
On Fri, 23 Jan 2009 04:28:33 -0800, unineuro wrote: Hi, I want to add some properties dynamically to a class, and then add the corresponding getter methods. Something resulting in this: class Person: def Getname(self): return self.__name def Getage(self): return self.__age (1) Properties don't work with classic classes. If you have setters to go with these getters, and you're using Python 2.x, your code will fail to work the way you think it should. (2) Getters and setters are generally discouraged in Python unless you really need them. If all you are doing is getting/setting an attribute, then you're just wasting time. (Or if this is a learning exercise.) I've implemented the next code, creating the properties from a list: props = [ (name, peter), (age, 31), (wife, mary) ] 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])) Seems awfully complicated. I'm not even sure it will work, due to Python's name-mangling. And let's not even talk about how broken it is to get your input to a class initializer from a global variable! What happens when you need a second instance? if __name__ == __main__: person = Person() print person.__name print person.__age print person.__wife print print person.Getname() print person.Getage() print person.Getwife() And the resulting execution of this program is: peter 31 mary mary mary mary 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? class Person(object): def __init__(self, name, age, wife): self.name = name self.age = age self.wife = wife props = {name: peter, age: 31, wife: mary} if __name__ == __main__: person = Person(**props) print person.name print person.age print person.wife If you really want getters, for whatever reason, then do it like this: class Person(object): def __init__(self, name, age, wife): self._name = name self._age = age self._wife = wife for prop in ('name', 'age', 'wife'): setattr(Person, prop, property( lambda self, prop=prop: getattr(self, '_'+prop) )) -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
unine...@gmail.com wrote: 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])) I've had a similar problem here and here is best how I can explain it. The prop in the lambda function is a closure by 'name' to the prop in the containing name space (__init__), so when the lambda function executes, it looks for the name 'prop' in this name space and uses it's value. After the 'for prop in props' loop is complete, 'prop' is left referring to the last item in props, so each lambda function would use it (mary) One solution is to not use lambda and avoid closures by using default arguments: for prop in props: def Getter(self=self, prop=prop): return getattr(self, '__' + prop[0]) setattr(self, '__' + prop[0], prop[1]) setattr(self, 'Get' + prop[0], Getter) I have several problems with this though: 1. I don't think this will invoke Pythons name mangling mechanism. The property will be '__name' and not '__Person_name'. 2. If you make a copy of the class, including attributes, the Getter will operate on the old class not new: Person a b = copy.copy(a) setattr(a, '__name', bob) setattr(b, '__name', sarah) b.Getname() - bob In order to make it work, the class must support updating the Getter when it is copied to have a new self value. import copy class MethodCaller: def __init__(self, obj, method, name): self.obj = obj self.method = method self.name = name setattr(obj, name, self) def __call__(self, *args, **kwargs): return self.method(self.obj, *args, **kwargs) def copy(self, newobj): return MethodCaller(newobj, self.method, self.name) props = ( ('name', 'mary'), ('age', 21), ('gender', 'female') ) class Person: def __init__(self): self._methods = [] for prop in props: (name, value) = prop def getter(self, name=name): return getattr(self, '_' + name) setattr(self, '_' + name, value) self._methods.append(MethodCaller(self, getter, 'Get' + name)) def copy(self,copymethods=True): c = copy.copy(self) if copymethods: c._methods = [] for i in self._methods: c._methods.append(i.copy(c)) return c # Example without copying methods p = Person() q = p.copy(False) p._name = 'sarah' q._name = 'michelle' print p.Getname() print p.Getage() print p.Getgender() print q.Getname() # Still prints 'sarah', because getter still refers to 'p' instead of 'q' print q.Getage() print q.Getgender() # Example with copying methods p = Person() q = p.copy() p._name = 'sarah' q._name = 'michelle' print p.Getname() print p.Getage() print p.Getgender() print q.Getname() # Prints 'michelle' print q.Getage() print q.Getgender() -- http://mail.python.org/mailman/listinfo/python-list
Re: Dynamic methods and lambda functions
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