440,235 Members | 1,008 Online
Need help? Post your question and get tips & solutions from a community of 440,235 IT Pros & Developers. It's quick & easy.

# Anonymus functions revisited

 P: n/a Since George Sakkis proposed a new way of doing list comprehensions http://groups-beta.google.com/group/...ff1b81fa70c8a7 letting tuples-like objects (x,y,z=0) acting as functions on other tuples I wonder why this would not be a good starting point of rethinking anonymus functions? In Georges proposition the action is (x,y,z=0) -> (x,y,z) i.e. mapping tuples on other tuples. This is equivalent to lambda x,y,z=0:(x,y,z) But regarding tuples as actions by means of an arrow "->" would generalize this idea: Mappings like that: ((x,y),z) -> x+y-z ((x,y=0),z) -> None should be valid actions too. What is the audience thinking about that? Regards Kay Jul 18 '05 #1
37 Replies

 P: n/a Kay Schluehr wrote: Since George Sakkis proposed a new way of doing list comprehensions http://groups-beta.google.com/group/...ff1b81fa70c8a7 letting tuples-like objects (x,y,z=0) acting as functions on other tuples I wonder why this would not be a good starting point of rethinking anonymus functions? In Georges proposition the action is (x,y,z=0) -> (x,y,z) i.e. mapping tuples on other tuples. This is equivalent to lambda x,y,z=0:(x,y,z) But regarding tuples as actions by means of an arrow "->" would generalize this idea: Mappings like that: ((x,y),z) -> x+y-z ((x,y=0),z) -> None should be valid actions too. What is the audience thinking about that? IMHO, it's just lambda in disguise, and I'm not sure it's more readable than lambda. You'll have to provide more arguments (sorry for the pun !-) to gain my adhesion. (NB : I could use this syntax without problem, it's just that we already have a syntax for this). -- bruno desthuilliers python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for p in 'o****@xiludom.gro'.split('@')])" Jul 18 '05 #2

 P: n/a On 21 Mar 2005 22:37:42 -0800, "Kay Schluehr" wrote: Mappings like that: ((x,y),z) -> x+y-z ((x,y=0),z) -> Noneshould be valid actions too.What is the audience thinking about that? I think that there's too much implied, and that in the long run it, if we keep addding in special shortcuts, it will lead to very dificult to read code. Jul 18 '05 #3

 P: n/a > letting tuples-like objects (x,y,z=0) acting as functions on other tuples I wonder why this would not be a good starting point of rethinking anonymus functions? In Georges proposition the action is (x,y,z=0) -> (x,y,z) i.e. mapping tuples on other tuples. This is equivalent to lambda x,y,z=0:(x,y,z) As you say for yourself, that's just lambda in disguise. So I guess the same arguments about the in- or exclusion of lambda apply here. I personally like lambda, but _can_ live without it. -- Regards, Diez B. Roggisch Jul 18 '05 #4

 P: n/a bruno modulix wrote: Kay Schluehr wrote: Since George Sakkis proposed a new way of doing list comprehensions http://groups-beta.google.com/group/...ff1b81fa70c8a7 letting tuples-like objects (x,y,z=0) acting as functions on other tuples I wonder why this would not be a good starting point of rethinking anonymus functions? In Georges proposition the action is (x,y,z=0) -> (x,y,z) i.e. mapping tuples on other tuples. This is equivalent to lambda x,y,z=0:(x,y,z) which is in fact not a valid solution in the context of Georges' problem... (or I failed to get it to work !-) But regarding tuples as actions by means of an arrow "->" would generalize this idea: Mappings like that: ((x,y),z) -> x+y-z ((x,y=0),z) -> None should be valid actions too. What is the audience thinking about that? IMHO, it's just lambda in disguise, and I'm not sure it's more readable than lambda. You'll have to provide more arguments (sorry for the pun !-) to gain my adhesion. (NB : I could use this syntax without problem, it's just that we already have a syntax for this). Changing my mind after a more torough re-reading of the original thread and few tests... The original problem is about tuple unpacking. The proposed solution solves this problem, *and* can (could ?) be a replacement for lambdas. hmmm... I like the idea of having a more flexible tuple unpacking with a function-call-like semantic, but I'm still not sure to like the idea of replacing lambda with the proposed syntax. needs-some-more-thinking-on-this-ly'yrs -- bruno desthuilliers python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for p in 'o****@xiludom.gro'.split('@')])" Jul 18 '05 #5

 P: n/a Diez B. Roggisch wrote:letting tuples-like objects (x,y,z=0) acting as functions on othertuples I wonder why this would not be a good starting point ofrethinking anonymus functions?In Georges proposition the action is (x,y,z=0) -> (x,y,z)i.e. mapping tuples on other tuples. This is equivalent tolambda x,y,z=0:(x,y,z) As you say for yourself, that's just lambda in disguise. Not exactly in fact - unless I messed something. There are 2 problems here: a more flexible tuple unpacking, *and* a lambda in disguise. Actually, I'd go + 1 for the first, -1 for the second So I guess the same arguments about the in- or exclusion of lambda apply here. For the second part, yes. Not for the first one. I personally like lambda, but _can_ live without it. Yes, one can live without... ....and without list comprehensions, __call__ and other special methods, descriptors, metaclasses, first class functions, builtin datatypes like lists and dicts, exceptions, dynamic typing, garbage collection, etc too. Hurray, let's all happily program in assembly !-) -- bruno desthuilliers ruby -e "print 'o****@xiludom.gro'.split('@').collect{|p| p.split('.').collect{|w| w.reverse}.join('.')}.join('@')" Jul 18 '05 #6

 P: n/a > Not exactly in fact - unless I messed something. There are 2 problems here: a more flexible tuple unpacking, *and* a lambda in disguise. Actually, I'd go + 1 for the first, -1 for the second The proposed syntax from Kay is lambda in disguise. To make it work like George want it is modifying the unpacking behaviour. Actually while Kay proposed his syntax as result of the discussion started by George it won't work for that case. The reason is simply that the lambda form returns a tuple, but does not make any revelations about the variable names that tuple shall be unpacked to. So they are in fact unrelated - at least if introduced as declared. An augmentation to fulfill George's wishes could look like this: [a,b,c for a,b,c: (x,y,z=0)-> x,y,z) in values] Yes, one can live without... ...and without list comprehensions, __call__ and other special methods, descriptors, metaclasses, first class functions, builtin datatypes like lists and dicts, exceptions, dynamic typing, garbage collection, etc too. Hurray, let's all happily program in assembly !-) You are right, but for lambda in its current limited form short, named functions are a good replacement. I don't want to get rid of lambda - but since listcomps got introduced, 95% of my usages of them disappeared. -- Regards, Diez B. Roggisch Jul 18 '05 #7

 P: n/a On Tue, 22 Mar 2005 15:05:55 +0100, bruno modulix wrote: bruno modulix wrote: Kay Schluehr wrote: Since George Sakkis proposed a new way of doing list comprehensions letting tuples-like objects (x,y,z=0) acting as functions on other tuples I wonder why this would not be a good starting point of rethinking anonymus functions? In Georges proposition the action is (x,y,z=0) -> (x,y,z) What about a safe exec as a replacement to lamba but witht he flexability of exec in a safe and limeted way? safe_exec ( (*inputs) , (expressionstring) , ( *outputs) ) Functon to return a default value: def dfv( arg = value): return arg Safe exec command: x, y = 1, 2 safeexec ( (x, y, dfv(z=0)), "# do nothing", ( x, y, z) ) (1, 2, 0) What could we do, not do with this? * I actually started this reply here, so below is how I got to the above exression. I'm trying to put my finger on the basic inconsistency here. It has something to do with the z=0 as a way to defining a default . Then there's the lamba which I hear may be removed, but is difficult to understand for beginners, and isn't readable in that the name doesn't say what it does. An alternative name, and possibly a simpler syntax would be a plus. Another concept that this touches is the indirect execution of an expression. Exec and eval do that, but then you introduce security issues. I'm wondering if there's a fundamental concept under these issues such as a base function class or command that can evaluate the contents of a tuple in a secure way? value = fn(arg, returnvalue) x = 1 fn( x, x*2) 2 Use lists or tuples for multiple arguments and return expressions: x, y, z = 1, 2, 3 fn( (x,y,z=0), (x,y,z) ) (1, 2, 3) But it's that "z=0" causes problems here. In a tuple it's equivalent to saying 1=2. or 'a'='b' So we need a way to say 'if name is undefined, bind it to object'. # function to give a default value def dfv( arg = value): return arg x, y = 1, 2 fn( (x, y, dfv(x=0)), ( x, y, z )) (1, 2, 3) Now since this could execute in it's own private space, it might also offer a way to use exec or eval() indirectly in a very limited and safe way. estring = \ """ result = '' data = 'abcdefghigklmnop' for ch in data: if ch != filterc: result.join(ch) """ fn( ( dfv(filterc='d'), evalstring), (exec estring) ) So we need to use a three item tuple: safe_exec ( (*inputs) , (expressionstring) , ( *outputs) ) def dfv( arg = value): return arg x, y = 1, 2 safeexec( (x, y, dfv(z=0)), "# do nothing", ( x, y, z) ) (1, 2, 0) Long way around to here, but is this something that has potential? It would have to be a built in to ensure it's safe to use. But with an exec string, it can possibly do a lot more than lamba, and it probably wouldn't be as fast. But the flexibility could be useful. Ron Jul 18 '05 #8

 P: n/a Ron a écrit : (snip)def dfv( arg = value): return arg def dfv( arg = value): .... return arg .... Traceback (most recent call last): File "", line 1, in ? NameError: name 'value' is not defined And sorry, but -1 for using exec here. Jul 18 '05 #9

 P: n/a Ron a écrit : On 21 Mar 2005 22:37:42 -0800, "Kay Schluehr" wrote:Mappings like that: ((x,y),z) -> x+y-z ((x,y=0),z) -> Noneshould be valid actions too.What is the audience thinking about that? I think that there's too much implied, and that in the long run it, if we keep addding in special shortcuts, it will lead to very dificult to read code. Don't like Perl ?-) The problem here is that Kay's proposition mixes two points: flexible tuple unpacking and a new syntax for anonymous functions. Jul 18 '05 #10

 P: n/a Diez B. Roggisch a écrit : (snip) You are right, but for lambda in its current limited form short, named functions are a good replacement. -inf on this !-) Jul 18 '05 #11

 P: n/a On Tue, 22 Mar 2005 21:43:48 +0100, Bruno Desthuilliers wrote: Ron a écrit :(snip)def dfv( arg = value): return arg def dfv( arg = value):... return arg...Traceback (most recent call last): File "", line 1, in ?NameError: name 'value' is not definedAnd sorry, but -1 for using exec here. Yes, I cought that myself. So... try: z=z except: z=0 or if 'z' not in locals(): z = 0 Ok, thinking in more incremental terms... Why should a function not create a local varable of an argument if the varable doesn't exist and a default value is given? So when: Def dfv( v=0): return v dfv() 0 ;it creates the local copy in this case. a = 25dfv(a) 25 ;It used the given value as expected. dfv(b) Traceback (most recent call last): File "", line 1, in -toplevel- dfv(b) NameError: name 'b' is not defined Why not let it set the local varable v to the default as it does when no varable is specified? A function without a default would still give an error as expected. :) Ok no exec, but what about the general syntax? value = keyword (inputargs, command, outputargs) I was thinking if it can be done with standard tuples, it has the potential to be passed around easily and work from lists and dictionaries. Ron Jul 18 '05 #12

 P: n/a On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote: Why should a function not create a local varable of an argument if thevarable doesn't exist and a default value is given? ok... thought it out better. :) Getting a default into a function isn't the problem. Returning the value to a varable that doesn't exist is. So then the question is ... is there a way for a function to create a varable in it's parents namespace that persists after the function is done? Jul 18 '05 #13

 P: n/a "Ron" wrote: On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote:Why should a function not create a local varable of an argument if thevarable doesn't exist and a default value is given? ok... thought it out better. :) Getting a default into a function isn't the problem. Returning the value to a varable that doesn't exist is. So then the question is ... is there a way for a function to create a varable in it's parents namespace that persists after the function is done? Yeap.. a simple one-liner can do the trick: def makeVars(**nameVals): sys._getframe(1).f_locals.update(nameVals) try: b except NameError: print "Before makeVars: NameError" else: print "Before makeVars: Not NameError" makeVars(b=2) try: b except NameError: print "After makeVars: NameError" else: print "After makeVars: Not NameError" George Jul 18 '05 #14

 P: n/a On Tue, 22 Mar 2005 18:15:25 -0500, "George Sakkis" wrote: "Ron" wrote: On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote: >Why should a function not create a local varable of an argument if the >varable doesn't exist and a default value is given? Yeap.. a simple one-liner can do the trick:def makeVars(**nameVals): sys._getframe(1).f_locals.update(nameVals)try: bexcept NameError: print "Before makeVars: NameError"else: print "Before makeVars: Not NameError"makeVars(b=2)try: bexcept NameError: print "After makeVars: NameError"else: print "After makeVars: Not NameError"George Cool! Thanks George, so I can do this: # Set a varable to a default value if it doesn't exist. # Return the same value back if it does. # Use: varable = dfvalue( varable=object) def defvalue(**var): if var.keys()[0] not in sys._getframe(1).f_locals.keys(): return var.values()[0] return sys._getframe(1).f_locals[var.keys()[0]] f = defvalue(f=0) print f # 0 g = 19 g = defvalue(g=0) print g # 19 Would there be any problems with using this function? Not sure where I need it. Was thinking it could be used inside expressions somehow, and it was an iteresting problem. ;) Ron Jul 18 '05 #15

 P: n/a On Tue, 22 Mar 2005 21:45:42 +0100, Bruno Desthuilliers wrote: Ron a écrit : On 21 Mar 2005 22:37:42 -0800, "Kay Schluehr" wrote:Mappings like that: ((x,y),z) -> x+y-z ((x,y=0),z) -> Noneshould be valid actions too.What is the audience thinking about that? I think that there's too much implied, and that in the long run it, if we keep addding in special shortcuts, it will lead to very dificult to read code.Don't like Perl ?-) I tried it.. Wrote a html reformatter in it a long time ago. Wasn't tempted to do anything else with it. It was good for that, but I went a month later and had trouble figuring out how it worked. :) The problem here is that Kay's proposition mixes two points: flexibletuple unpacking and a new syntax for anonymous functions. Yes, two different problems. I don't think anything needs to be done to tuples myself. I tend to use lists more anyway. As far as anonymous functions go... What if there where a container type to hold unexecuted python code until it is asked to do it. And to be able to assign it a name, so it would have an object class and type. But be defined by like a tuple. No addition syntax to make things confusing. sum = (* a = b+c *) The (* and *) could be something more appropriate. As long as it's easy to identify and can't be confused with anything else. There would be an order of precedence to it also so you could do: my_button_action = (*a+=c (*if b:c=1 (*if not z: b=False*) *) *) It would execute from the inside (*_*) outward and use the local name space it's executed in, so no passing arguments or return values. Nesting and order of precedence has worked for a long time. to evaluate it you would need a keyword... newlamba my_button_action or this could be valid:newlamba (* a+=c (* if b:c=1 (* if not z:b=False *) *) *) or left to right order of execution:newlamba (* a = b+c+d, if a>limit:done=True *) If argument passing is really needed, I suppose there could be an export/inport method attached to it. newlamba (* sum = a+b *).import(a,b).export(sum) ornewlamba (* sum = a+b *).in_out(a,b -> sum) newlamba my_button_action.in_out(a,b ->sum) A differnt name would be nice... code, docode, dothis, process... ? or if you require the in_out method to start it, you don't need the keyword. mybutton = (* sum = a+b *) # does not execute, but binds it to a b = mybutton.in_out(a,b -> sum) # This evaluates first, the sum is bound to b. b = (* sum = a+b *).in_out(a,b -> sum) # Is the same as above. Yes, there are probably loads of stuff wrong with this. ;-) Ron Adam (Looks like another Ron joined the group.) Jul 18 '05 #16

 P: n/a Op 2005-03-22, Diez B. Roggisch schreef : Not exactly in fact - unless I messed something. There are 2 problems here: a more flexible tuple unpacking, *and* a lambda in disguise. Actually, I'd go + 1 for the first, -1 for the second The proposed syntax from Kay is lambda in disguise. To make it work like George want it is modifying the unpacking behaviour. Actually while Kay proposed his syntax as result of the discussion started by George it won't work for that case. The reason is simply that the lambda form returns a tuple, but does not make any revelations about the variable names that tuple shall be unpacked to. So they are in fact unrelated - at least if introduced as declared. An augmentation to fulfill George's wishes could look like this: [a,b,c for a,b,c: (x,y,z=0)-> x,y,z) in values] Yes, one can live without... ...and without list comprehensions, __call__ and other special methods, descriptors, metaclasses, first class functions, builtin datatypes like lists and dicts, exceptions, dynamic typing, garbage collection, etc too. Hurray, let's all happily program in assembly !-) You are right, but for lambda in its current limited form short, named functions are a good replacement. I don't want to get rid of lambda - but since listcomps got introduced, 95% of my usages of them disappeared. I don't understand why people always say short named functions are a good replacement. IMO list comprehensions and generator expressions use lambda's in disguise. When we write something like [x * x for x in some_iterator], nobody seems to have problems that we just write an expression here and nobody is argueing that we should define a short function. However when people need the same kind of semantics in their function, being an expression that is being reevaluated with different values, for which lambda is the natural candidate, suddenly we should use short named functions. Can someone who thinks this way, please explain why this is acceptable [ x * x for x in some_iterator ] But this is not map(lambda x: x * x, some_iteraror) and should be replaced with def sqr(x): return x * x map(sqr , some_iterator) -- Antoon Pardon Jul 18 '05 #17

 P: n/a Ron wrote: On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote:Why should a function not create a local varable of an argument if thevarable doesn't exist and a default value is given? ok... thought it out better. :) Getting a default into a function isn't the problem. Returning the value to a varable that doesn't exist is. So then the question is ... is there a way for a function to create a varable in it's parents namespace that persists after the function is done? yes, that'w called a global, and it's UGLY(tm) def yuck(): .... global G .... G = 42 .... G Traceback (most recent call last): File "", line 1, in ? NameError: name 'G' is not defined yuck() G 42 Anyone doing such a thing in my team would be shoot down at once !-) -- bruno desthuilliers python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for p in 'o****@xiludom.gro'.split('@')])" Jul 18 '05 #18

 P: n/a George Sakkis wrote: "Ron" wrote:On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote:Why should a function not create a local varable of an argument if thevarable doesn't exist and a default value is given?ok... thought it out better. :)Getting a default into a function isn't the problem. Returning thevalue to a varable that doesn't exist is.So then the question is ... is there a way for a function to create avarable in it's parents namespace that persists after the function isdone? Yeap.. a simple one-liner can do the trick: def makeVars(**nameVals): sys._getframe(1).f_locals.update(nameVals) try: b except NameError: print "Before makeVars: NameError" else: print "Before makeVars: Not NameError" makeVars(b=2) try: b except NameError: print "After makeVars: NameError" else: print "After makeVars: Not NameError" Interesting. I'll keep a copy of this one in my cookbook for further exploration. But I think I would use such a thing in production code. b = 25 makeVars(b=88) b 88 -- bruno desthuilliers python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for p in 'o****@xiludom.gro'.split('@')])" Jul 18 '05 #19

 P: n/a Ron wrote: On Tue, 22 Mar 2005 21:45:42 +0100, Bruno Desthuilliers wrote:Ron a écrit :On 21 Mar 2005 22:37:42 -0800, "Kay Schluehr" wrote: Mappings like that: ((x,y),z) -> x+y-z ((x,y=0),z) -> Noneshould be valid actions too.What is the audience thinking about that? I think that there's too much implied, and that in the long run it,if we keep addding in special shortcuts, it will lead to very dificultto read code.Don't like Perl ?-) I tried it.. Wrote a html reformatter in it a long time ago. Wasn't tempted to do anything else with it. It was good for that, but I went a month later and had trouble figuring out how it worked. :) This was kind of rethorical question !-) The problem here is that Kay's proposition mixes two points: flexibletuple unpacking and a new syntax for anonymous functions. Yes, two different problems. I don't think anything needs to be done to tuples myself. I tend to use lists more anyway. They are two different beasts. Note that you don't have anything like list unpacking, now tuple unpacking is pretty common in Python (swap, multiple return values, formatted strings and outputs, ...). As far as anonymous functions go... (snip prospective code) Yes, there are probably loads of stuff wrong with this. ;-) Err... Isn't it a bit more complicated than our actual lambdas ?-) -- bruno desthuilliers ruby -e "print 'o****@xiludom.gro'.split('@').collect{|p| p.split('.').collect{|w| w.reverse}.join('.')}.join('@')" Jul 18 '05 #20

 P: n/a George Sakkis wrote: So then the question is ... is there a way for a function to create a varable in it's parents namespace that persists after the function is done? Yeap.. a simple one-liner can do the trick: def makeVars(**nameVals): sys._getframe(1).f_locals.update(nameVals) try: b except NameError: print "Before makeVars: NameError" else: print "Before makeVars: Not NameError" makeVars(b=2) try: b except NameError: print "After makeVars: NameError" else: print "After makeVars: Not NameError" Do I really need to mention that the whole concept here is broken. This only works if you call it from global scope. If you call it from inside a function it [usually] won't work: def makeVars(**nameVals): sys._getframe(1).f_locals.update(nameVals) def test(): try: b except NameError: print "Before makeVars: NameError" else: print "Before makeVars: Not NameError" makeVars(b=2) try: b except NameError: print "After makeVars: NameError" else: print "After makeVars: Not NameError" import sys test() Before makeVars: NameError After makeVars: NameError Jul 18 '05 #21

 P: n/a > Can someone who thinks this way, please explain why this is acceptable [ x * x for x in some_iterator ] But this is not map(lambda x: x * x, some_iteraror) and should be replaced with def sqr(x): return x * x map(sqr , some_iterator) It shouldn't, it should be replaced with the listcomp. And IMHO it results in better readable code. AFAIK the reason people say you should use named functions is _not_ because of these single expression replacements. The reason is that frequently people complain about lambda being so restrictive so that you can't write lambda x,y: if x > 100: x else: y and want to _extend_ lambda beyond its current capabilities and make it full featured but anonymous functions. And these requests are rebuked with the argument that having to give a more complex function a name instead of declaring it anonymously doesn't cost you much - especially since you can declare them inside other functions so the global namespace isn't cluttered. I have to admit that rereading my statement """ You are right, but for lambda in its current limited form short, named functions are a good replacement """ is not really what I wanted to say. I should have written: """ for lambda in its current limited form, listcomprehensions often are a good replacement. """ But as I've said various times before: I personally don't mind lambdas and for example the reduce function has been useful for me quite a few times, can't be replaced by listcomps, and frequently needs a callable consisting of only a single expression. So I'll continue to use lambdas there. -- Regards, Diez B. Roggisch Jul 18 '05 #22

 P: n/a Duncan Booth wrote: Do I really need to mention that the whole concept here is broken. This only works if you call it from global scope. If you call it from inside a function it [usually] won't work: def makeVars(**nameVals): sys._getframe(1).f_locals.update(nameVals) def test(): try: b except NameError: print "Before makeVars: NameError" else: print "Before makeVars: Not NameError" makeVars(b=2) try: b except NameError: print "After makeVars: NameError" else: print "After makeVars: Not NameError" import sys test() Before makeVars: NameError After makeVars: NameError Yes. To put it short: def makeVars(**nameVals): print "prev",sys._getframe(1).f_locals["z"] sys._getframe(1).f_locals.update(nameVals) print "post",sys._getframe(1).f_locals["z"] def test(): z = 0 makeVars(z=2) z = 0 makeVars(z=3) prev 0 post 3 test() prev 0 post 0 The Python runtime uses the opcodes STORE_FAST and LOAD_FAST to store/access local variables of a function. Take a closer look at the code: case STORE_FAST: v = POP(); SETLOCAL(oparg, v); goto fast_next_opcode; with register PyObject **fastlocals and macros #define GETLOCAL(i) (fastlocals[i]) #define SETLOCAL(i, value) do { PyObject *tmp = GETLOCAL(i); \ GETLOCAL(i) = value; \ Py_XDECREF(tmp); } while (0) The local variables will be stored in the pointer array fastlocals not within a Python dict. If a variable is created as a global it will be stored using the STORE_NAME opcode instead: case STORE_NAME: w = GETITEM(names, oparg); v = POP(); if ((x = f->f_locals) != NULL) { if (PyDict_CheckExact(x)) err = PyDict_SetItem(x, w, v); else err = PyObject_SetItem(x, w, v); Py_DECREF(v); if (err == 0) continue; break; } which clearly accesses a Python dict for storage. Regards Kay Jul 18 '05 #23

 P: n/a Op 2005-03-23, Diez B. Roggisch schreef : Can someone who thinks this way, please explain why this is acceptable [ x * x for x in some_iterator ] But this is not map(lambda x: x * x, some_iteraror) and should be replaced with def sqr(x): return x * x map(sqr , some_iterator) It shouldn't, it should be replaced with the listcomp. And IMHO it results in better readable code. This misses the point. The fact that map and the listcomprehension do the same stuff is just a detail. It is about giving a function an expression as argument that is to be evaluated multiple times. AFAIK the reason people say you should use named functions is _not_ because of these single expression replacements. The reason is that frequently people complain about lambda being so restrictive so that you can't write lambda x,y: if x > 100: x else: y and want to _extend_ lambda beyond its current capabilities and make it full featured but anonymous functions. This is one kind of people. An other kind of people seems to want to get rid of lamda's altogether and asks whether it is so difficult to make a named function each time you would otherwise use a lambda. But as I've said various times before: I personally don't mind lambdas and for example the reduce function has been useful for me quite a few times, can't be replaced by listcomps, and frequently needs a callable consisting of only a single expression. So I'll continue to use lambdas there. Then my question was not meant for you. -- Antoon Pardon Jul 18 '05 #24

 P: n/a On 23 Mar 2005 10:13:16 GMT, Duncan Booth wrote: Do I really need to mention that the whole concept here is broken. Thisonly works if you call it from global scope. If you call it from inside afunction it [usually] won't work: That's only becuase it was asked to go up 1 frame, and not 2. def makeVars(**nameVals): sys._getframe(2).f_locals.update(nameVals) # <- get 2 frames up. def test(): try: b except NameError: print "Before makeVars: NameError" else: print "Before makeVars: Not NameError" makeVars(b=2) try: b except NameError: print "After makeVars: NameError" else: print "After makeVars: Not NameError" import sys test() Before makeVars: NameError After makeVars: Not NameError Jul 18 '05 #25

 P: n/a On 23 Mar 2005 10:13:16 GMT, Duncan Booth wrote: Do I really need to mention that the whole concept here is broken. Thisonly works if you call it from global scope. If you call it from inside afunction it [usually] won't work: Ok... you can get globals this way if you know how many frames up it is. Not terrable useful. :/ def frame0(): print 'frame0 (locals): ',sys._getframe(0).f_locals print '\nframe1 (parent): ',sys._getframe(1).f_locals print '\n(Global) : ',sys._getframe(2).f_locals def frame1(): frame0() import sys frame1() frame0 (locals): {} frame1 (parent): {} (Global) : {'__builtins__': , 'sys': , '__name__': '__main__', 'frame1': , 'frame0': , '__doc__': None} Jul 18 '05 #26

 P: n/a Ron wrote: On 23 Mar 2005 10:13:16 GMT, Duncan Booth wrote: Do I really need to mention that the whole concept here is broken. This only works if you call it from global scope. If you call it from inside a function it [usually] won't work: That's only becuase it was asked to go up 1 frame, and not 2. def makeVars(**nameVals): sys._getframe(2).f_locals.update(nameVals) # <- get 2 frames up. def test(): try: b except NameError: print "Before makeVars: NameError" else: print "Before makeVars: Not NameError" makeVars(b=2) try: b except NameError: print "After makeVars: NameError" else: print "After makeVars: Not NameError" import sys test() Before makeVars: NameError After makeVars: Not NameError That's true only because the globals are updated by {"b":2} two levels down. If You nest the test() function You reproduce the error again: def test(): def inner(): try: b except NameError: print "Before makeVars: NameError" else: print "Before makeVars: Not NameError" makeVars(b=2) try: b except NameError: print "After makeVars: NameError" else: print "After makeVars: Not NameError" inner() Before makeVars: NameError After makeVars: NameError A working makeVars seems not to be different from def makeVars(**nameVals): globals().update(nameVals) Regards Kay Jul 18 '05 #27

 P: n/a Kay Schluehr wrote: A working makeVars seems not to be different from def makeVars(**nameVals): globals().update(nameVals) Not quite. If Ron can come up with a working makeVars it would update the caller's globals whereas what you just posted updates makeVar's globals so there is a difference (when the makeVars and the calling function are in different modules), just not a very useful one. Jul 18 '05 #28

 P: n/a On 23 Mar 2005 08:31:36 GMT Antoon Pardon wrote: Can someone who thinks this way, please explain why this is acceptable [ x * x for x in some_iterator ] But this is not map(lambda x: x * x, some_iteraror) and should be replaced with def sqr(x): return x * x map(sqr , some_iterator) I guess I have similar feelings. I've only been using python for a year or two, so I'm still a relative newcomer. Like a lot of people, I found Python to be magically simple and intuitive. But I've never really found list comprehensions particularly clear. I don't know whether it's my backgroud (mainly C/C++), or my brain or what, but they are probably the only thing in Python that hasn't seemed transparent and obvious to me (apart from shadowing of variables in nested functions). Of course, I'm sure I could get used to them, given time. But that rather defeats one of the main reasons for using python in the first place - the lack of a steep learning curve. In contrast, I find lambdas, even with their significant restrictions, to be much more obvious. In fact, the proposal (sorry, don't have a link to hand) about extending lambda to allow things like `myfn = def ' was something that I initially assumed would become part of the language in time. Is there some definitive information that explains why python is moving away from lambdas and towards things like list comprehensions? - Julian -- http://www.op59.net/ Jul 18 '05 #29

 P: n/a "bruno modulix" wrote: in message news:42**********************@news.free.fr... Ron wrote:The problem here is that Kay's proposition mixes two points: flexibletuple unpacking and a new syntax for anonymous functions. Yes, two different problems. I don't think anything needs to be done to tuples myself. I tend to use lists more anyway. They are two different beasts. Note that you don't have anything like list unpacking, now tuple unpacking is pretty common in Python (swap, multiple return values, formatted strings and outputs, ...). All the following are possible: (x,y,z) = (1,2,3) (x,y,z) = [1,2,3] [x,y,z] = (1,2,3) [x,y,z] = [1,2,3] What exactly do you mean by "don't have anything like list unpacking" ? George Jul 18 '05 #30

 P: n/a On 23 Mar 2005 14:47:30 GMT, Duncan Booth wrote: Kay Schluehr wrote: A working makeVars seems not to be different from def makeVars(**nameVals): globals().update(nameVals)Not quite. If Ron can come up with a working makeVars it would update thecaller's globals whereas what you just posted updates makeVar's globals sothere is a difference (when the makeVars and the calling function are indifferent modules), just not a very useful one. How about this one? The only reliable way I found to do it is to pass locals() to the function. def defvalue(**args): args = args.items() a1 = args[0] a2 = args[1] if type(a1[1]) == type({}): vv, names = a2, a1[1] else: vv, names = a1, a2[1] if names.has_key(vv[0]): return names[vv[0]] return vv[1] f = defvalue(f=1, v=locals()) print f # 0 g = 19 g = defvalue(g=2, v=locals()) print g # 19 z = 6 def f1(): #z = 4 z = defvalue(z=3, v=locals()) print z f1() Jul 18 '05 #31

 P: n/a George Sakkis wrote: "bruno modulix" wrote: in message news:42**********************@news.free.fr... (snip) Note that you don't have anything likelist unpacking, now tuple unpacking is pretty common in Python (swap,multiple return values, formatted strings and outputs, ...). All the following are possible:(x,y,z) = (1,2,3)(x,y,z) = [1,2,3][x,y,z] = (1,2,3)[x,y,z] = [1,2,3] What exactly do you mean by "don't have anything like list unpacking" ? A stupidity :( -- bruno desthuilliers ruby -e "print 'on***@xiludom.gro'.split('@').collect{|p| p.split('.').collect{|w| w.reverse}.join('.')}.join('@')" Jul 18 '05 #32

 P: n/a Ron wrote: A working makeVars seems not to be different from def makeVars(**nameVals): globals().update(nameVals)Not quite. If Ron can come up with a working makeVars it would updatethe caller's globals whereas what you just posted updates makeVar'sglobals so there is a difference (when the makeVars and the callingfunction are in different modules), just not a very useful one. How about this one? The only reliable way I found to do it is to pass locals() to the function. Yes, but you are still missing the fundamental point. The locals() dictionary is not guaranteed to do anything useful if you update it. The current C implementation will reflect changes in the locals dictionary if you call locals() from global scope or in a few other circumstances, but this is simply an implementation detail. If you want to update global variables then use globals() or setattr on the module. Only use locals() to access local variables indirectly, never to try and set them. Jul 18 '05 #33

 P: n/a On 24 Mar 2005 09:20:52 GMT, Duncan Booth wrote: Ron wrote: A working makeVars seems not to be different from def makeVars(**nameVals): globals().update(nameVals)Not quite. If Ron can come up with a working makeVars it would updatethe caller's globals whereas what you just posted updates makeVar'sglobals so there is a difference (when the makeVars and the callingfunction are in different modules), just not a very useful one. How about this one? The only reliable way I found to do it is to pass locals() to the function.Yes, but you are still missing the fundamental point. The locals()dictionary is not guaranteed to do anything useful if you update it. Thecurrent C implementation will reflect changes in the locals dictionary ifyou call locals() from global scope or in a few other circumstances, butthis is simply an implementation detail. Nope, Didn't miss the point. The functions return a value, not create it from within. If you want to update global variables then use globals() or setattr on themodule. Only use locals() to access local variables indirectly, never totry and set them. Good advise. :) One of pythons weak points is it is sometimes difficult to 'monitor and confirm' what is happening leading to confusing try/except constructions. Having the function is_defined() and if_not_defined() have the advantage that they can be use in expressions where try/except can't. And the source code could be more compact and more readable. The disadvantage is the functions are quite a bit slower than try/except, probably due to the function call over head. If they were built in, they may be as fast as the try/except and there wouldn't be issues with having to passing locals() or globals() name dictionaries. It's interesting that there is a whole is_"type"_() group of functions in the inspect module, but not a is_defined(). Maybe I just haven't found it yet. ############# def if_not_defined(v, dv=None, lv=locals()): if lv.has_key(v): return lv[v] return dv def is_defined(v, lv=locals()): if lv.has_key(v): return True False # Shorten names and pass locals() with lambas for # convenience. (This needs to be in the function # where they are used or it will break. # Another use for lamba! ;) ifnd = lambda v, dv, lv=locals(): if_not_defined(v,dv,lv) isa = lambda v, lv=locals(): is_defined(v, lv) # Totally useless routine. ;) import random for n in range(10): # Delete a random x,y,z coordinate to # simulate an unreliable data source. d = random.choice([1,2,3]) if d==1: if isa('x'): del x elif d==2: if isa('y'): del y else: if isa('z'): del z # Replace the missing variable with a random number. r = int(random.random()*100) x, y, z = ifnd('x',r), ifnd('y',r), ifnd('z',r) print x, y, z ########### Jul 18 '05 #34

 P: n/a Ron wrote: It's interesting that there is a whole is_"type"_() group of functions in the inspect module, but not a is_defined(). Maybe I just haven't found it yet. I've never found any need for an is_defined function. If in doubt I just make sure and initialise all variables to a suitable value before use. However, I'll assume you have a good use case. ############# def if_not_defined(v, dv=None, lv=locals()): if lv.has_key(v): return lv[v] return dv I don't see the point of the default argument. locals() at the global level simply returns globals, so you might as well use that. A more useful default would be the caller's locals. def is_defined(v, lv=locals()): if lv.has_key(v): return True False Same comments, plus the whole 'if on a boolean to return a boolean' is a bit redundant. Try something on these lines: import inspect def is_defined(name, lv=None): if lv is None: lv = inspect.currentframe().f_back.f_locals return name in lv is_defined('abc') False abc = 3 is_defined('abc') True def f(x): print is_defined('x') print is_defined('y') y = 0 print is_defined('y') f(2) True False True # Shorten names and pass locals() with lambas for # convenience. (This needs to be in the function # where they are used or it will break. # Another use for lamba! ;) ifnd = lambda v, dv, lv=locals(): if_not_defined(v,dv,lv) isa = lambda v, lv=locals(): is_defined(v, lv) There is no need for lambda here, it adds nothing. Use a 'def'. Jul 18 '05 #35

 P: n/a On 25 Mar 2005 10:09:50 GMT, Duncan Booth wrote: I've never found any need for an is_defined function. If in doubt I justmake sure and initialise all variables to a suitable value before use.However, I'll assume you have a good use case. I admit that that is the better practice. George's example was the conversion of data from one form to another where the data is mixed with complete and incomplete items. And Kay is looking at tuple unpacking. It's hard to beat try/except for these situations though. :) I cleaned it up some more and figured out the proper use of _getframe(). So no lambdas, and no passing of locals needed., and it checks for globals and builtins before defining the default value so as not to over write a readable value. I'm not sure what the best behavior should be. Maybe a routine to tell where a name is, ie.. local, global, builtin, or a writable global? maybe isa() return the location or None.? I think that would be better. The best purpose for utilities like these is for debugging and getting feedback about the environment. So I'm thinking of putting them in a module for that purpose. I have a subroutine to list all the names attached to an object. I think I can add that a bit now too. #---Here's the code--------------------- import sys def isa(v): """ Check if a varable exists in the current (parent to this function), global, or builtin name spaces. use: bool = isa( str ) returns True or False """ plocals = sys._getframe(1).f_locals if plocals.has_key(v) or globals().has_key(v) or \ __builtins__.locals().has_key(v): return True return False def ifno(v, obj=None): """ Check if a varable does not exists, return a default value, otherwise return the varable obj. use: obj = ifno( str [,obj=None] ) if str exist, returns str's object if str does not exist, returns specified object """ plocals = sys._getframe(1).f_locals if plocals.has_key(v): return plocals[v] if globals().has_key(v): return globals()[v] if __builtins__.locals().has_key(v): return __builtins__.locals()[v] return obj def test(): """ Test isa() and ifno() functions: """ # Totally useless routine. ;) import random for n in range(25): # Delete a random x,y,z coordinate to # simulate an unrealiabe data source. d = random.choice([1,2,3]) if d==1: if isa('x'): del x elif d==2: if isa('y'): del y else: if isa('z'): del z # Replace the missing Varible with a random number. r = int(random.random()*100) x, y, z = ifno('x',r), ifno('y',r), ifno('z',r) print x, y, z if __name__ == '__main__': test() #------------------------------------- Jul 18 '05 #36

 P: n/a "Ron_Adam" wrote: On 25 Mar 2005 10:09:50 GMT, Duncan Booth wrote:I've never found any need for an is_defined function. If in doubt I justmake sure and initialise all variables to a suitable value before use.However, I'll assume you have a good use case. I admit that that is the better practice. George's example was the conversion of data from one form to another where the data is mixed with complete and incomplete items. And Kay is looking at tuple unpacking. It's hard to beat try/except for these situations though. :) I posted a recipe in python cookbook (http://aspn.activestate.com/ASPN/Coo.../Recipe/392768) for the subproblem I was interested in initially (variable-length iterable unpacking), and I prefer it over explicit try/except (but of course I'm biased :-)). Kay is proposing something even more general and powerful, and it will be interesting to see if all this brainstorming can be brought forward more 'formally', e.g. at a PEP or pre-PEP level. Regards, George Jul 18 '05 #37

 P: n/a On Fri, 25 Mar 2005 17:09:38 -0500, "George Sakkis" wrote: I posted a recipe in python cookbook(http://aspn.activestate.com/ASPN/Coo.../Recipe/392768) for the subproblem I was interestedin initially (variable-length iterable unpacking), and I prefer it over explicit try/except (but ofcourse I'm biased :-)). Kay is proposing something even more general and powerful, and it will beinteresting to see if all this brainstorming can be brought forward more 'formally', e.g. at a PEPor pre-PEP level.Regards,George Looks good George. :) I'm not sure what Kay is trying for, but it does look interesting. I'm all for new features as long as they are consistent and easy to use, and easy to remember as well. I keep finding ways to improve the little routines I'm playing with. ;) I'll probably post them in the cookbook also, and maybe put them together in a mod. A few more pieces and I should be able to build a name space explorer which I think will be good for debugging programs. I'm thinking you could put it in the program where you are having problems and it will open a tree type window where you can examine all the names and objects at that point. When done, close it and the programs continues. It will give you a little more info than sticking print statements hear and there. Ron Jul 18 '05 #38

### This discussion thread is closed

Replies have been disabled for this discussion.