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

# How do I do this? (eval() on the left hand side)

 P: n/a I am new to the Python language. How do I do something like this: I know that a = 3 y = "a" print eval(y) would give me a print out of 3 - but how do I do something to the effect of: eval(y) = 4 # hopefully the value of a gets changed to 4 ?? Thanks, -- It's me Jul 18 '05 #1
45 Replies

 P: n/a Hi It's me a = 3 y = "a" print eval(y) To get 'a' to be 4 here, you would say a = 4 I am not sure why you would want to do otherwise? Perhaps you could sketch out a little more about what you are trying to do? That would help a lot. Are you aiming for something like pointer emulation with simple datatypes? Thanks Caleb Jul 18 '05 #2

 P: n/a "Caleb Hattingh" wrote in message news:op**************@news.telkomsa.net... Hi It's me a = 3 y = "a" print eval(y) To get 'a' to be 4 here, you would say a = 4 Obviously but that's not what I wish to do. I am not sure why you would want to do otherwise? Perhaps you could sketch out a little more about what you are trying to do? That would help a lot. Are you aiming for something like pointer emulation with simple datatypes? In REXX, for instance, one can do a: interpret y' = 4' Since y contains a, then the above statement amongs to: a = 4 There are many situations where this is useful. For instance, you might be getting an input which is a string representing the name of a variable and you wish to evaluate the expression (like a calculator application, for instance). Thanks Caleb Jul 18 '05 #3

 P: n/a Sure, ok, I think I am with you now. You get a (e.g.) variable name as a string, and you KNOW how to evaluate it with "eval", but you also want to be able to assign back to (through) the string representation? One way (if I understand you correctly) is with the globals or locals dicts. Try this in IDLE: '>>> a = 3 '>>> y = 'a' '>>> eval(y) 3 '>>> d = locals() # Get a dictionary of local variables '>>> d['a'] 3 '>>> d[y] 3 '>>> d[y] = 8 # y is a string = 'a' '>>> a # The value of a is changed. 8 '>>> Is this kinda what you mean? I'm still new at this (and don't know REXX from Adam). Thanks Caleb There are many situations where this is useful. For instance, you might be getting an input which is a string representing the name of a variable and you wish to evaluate the expression (like a calculator application, for instance). Jul 18 '05 #4

 P: n/a "It's me" wrote in message news:Y0*******************@newssvr14.news.prodigy. com... In REXX, for instance, one can do a: interpret y' = 4' Since y contains a, then the above statement amongs to: a = 4 There are many situations where this is useful. For instance, you might be getting an input which is a string representing the name of a variable and you wish to evaluate the expression (like a calculator application, for instance). In Python, the canonical advice for this situation is, "Use a dictionary." This has a number of advantages, including keeping your user's namespace separate from your application's namespace. Plus it's easier to debug and maintain the code. But, if you absolutely, positively have to refer to your variable indirectly, you could do: exec "%s = 4" % y If y refers to the string "a", this will cause the variable a to refer to the value 4. -- I don't actually read my hotmail account, but you can replace hotmail with excite if you really want to reach me. Jul 18 '05 #5

 P: n/a It's me wrote: In REXX, for instance, one can do a: interpret y' = 4' Since y contains a, then the above statement amongs to: a = 4 The direct equivalent in Python would be a = 3 y = 'a' exec '%s = 4' % y The better question would be whether or not this as useful as one might thing in Python; if you find yourself doing this, often there are better ways to accomplish the same thing, such as using dictionaries. -- Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/ San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis But the system has no wisdom / The Devil split us in pairs -- Public Enemy Jul 18 '05 #6

 P: n/a On Wed, 2004-12-08 at 05:12, It's me wrote: There are many situations where this is useful. For instance, you might be getting an input which is a string representing the name of a variable and you wish to evaluate the expression (like a calculator application, for instance). While I do agree it can be handy, I also think that most possible uses are also _very_ _dangerous_ security-wise. If possible it'd be safer to write your code a different way to avoid the evaluation of user-supplied expressions. For example, you could use a dictionary to store the 'user-accessible' namespace and have all their operations act on that. You could probably do something _like_ what you want with exec() and repr, but it'll break as soon as it encounters input that repr can't make an exec()able string from. It's also really ugly. If you know what namespace you want to modify ahead of time, or can pass it to the function doing the modifying, you can also use getattr()/setattr() or dict methods to do it. For example: # modify the globals space on the __main__ module import __main__ varname = 'fred' setattr(__main__, varname, 'blech') fred 'blech' # same thing __main__.__dict__[varname] = 'yech!' fred 'yech!' # modify the attributes of some random object class dummy(object): .... pass .... obj = dummy() setattr(obj, varname, 'eew') obj.fred 'eew' # same thing using the object's __dict__, NOT RECOMMENDED # outside the class's own methods. obj.__dict__[varname] = 'unwise' obj.fred 'unwise' This, however, won't do you much good if you don't know what you'll be modifying. I know the locals() and globals() functions exist, but have always been leery of the idea of modifying their contents, and am not sure what circumstances you could do so under even if you felt like doing so. In general, it'll be _much_ safer to use a generic object with getattr/setattr or a dict than to try to work with your local or global namespaces like this... -- Craig Ringer Jul 18 '05 #7

 P: n/a It's me wrote: How do I do something like this: I know that a = 3 y = "a" print eval(y) would give me a print out of 3 - but how do I do something to the effect of: eval(y) = 4 # hopefully the value of a gets changed to 4 Generally, if you find yourself doing this, you may want to rethink your program organization. That being said, if you are in the global scope, one option looks something like: a = 3 y = 'a' globals()[y] = 4 a 4 If you can give us some more context on why you want to do this, we can probably suggest a better approach. There aren't too many places where even advanced Python programmers need to use eval... Steve Jul 18 '05 #8

 P: n/a Yes, Russell, what you suggested works. I have to chew more on the syntax to see how this is working. because in the book that I have, it says: exec code [ in globaldict [, localdict] ] .... -- It's me "Russell Blau" wrote in message news:31*************@individual.net... "It's me" wrote in message news:Y0*******************@newssvr14.news.prodigy. com... In REXX, for instance, one can do a: interpret y' = 4' Since y contains a, then the above statement amongs to: a = 4 There are many situations where this is useful. For instance, you might be getting an input which is a string representing the name of a variable and you wish to evaluate the expression (like a calculator application, for instance). In Python, the canonical advice for this situation is, "Use a dictionary." This has a number of advantages, including keeping your user's namespace separate from your application's namespace. Plus it's easier to debug and maintain the code. But, if you absolutely, positively have to refer to your variable indirectly, you could do: exec "%s = 4" % y If y refers to the string "a", this will cause the variable a to refer to the value 4. -- I don't actually read my hotmail account, but you can replace hotmail with excite if you really want to reach me. Jul 18 '05 #9

 P: n/a Thanks for all the replies and yes I realize the associated issue of doing something like this. For simplicity sake, let's say I need to do something like this (for whatever reason): In situations like this, I wouldn't know the name of the variable in Python I need to use ahead of time and so I would have to somehow convert a string to be used as variable. Of course, I can create a dictionary to keep track of which variable has what name and this method of using exec should be avoid if at all possible. I am just trying to understand the language and see what it can do. -- It's me "Steven Bethard" wrote in message news:Ypptd.152996\$V41.76678@attbi_s52... It's me wrote: How do I do something like this: I know that a = 3 y = "a" print eval(y) would give me a print out of 3 - but how do I do something to the effect of: eval(y) = 4 # hopefully the value of a gets changed to 4 Generally, if you find yourself doing this, you may want to rethink your program organization. That being said, if you are in the global scope, one option looks something like: >>> a = 3 >>> y = 'a' >>> globals()[y] = 4 >>> a 4 If you can give us some more context on why you want to do this, we can probably suggest a better approach. There aren't too many places where even advanced Python programmers need to use eval... Steve Jul 18 '05 #10

 P: n/a It's me wrote: For simplicity sake, let's say I need to do something like this (for whatever reason): If I had a situation like this, I'd probably store my 'variables' as keys in a dict, e.g.: bindings = {} for i in range(3): .... name = raw_input('Name: ') .... value = int(raw_input('Value for %r: ' % name)) .... bindings[name] = value .... <... after inputting 'eggs', '7', 'badger', '42', 'spam', '13' ...> bindings {'eggs': 7, 'badger': 42, 'spam': 13} Once you have the 'variables' in a dict, you can just use the dict values in any expressions you need. bindings['eggs'] * bindings['badger'] 294 I am just trying to understand the language and see what it can do. Well, it can do a lot, but the folks on this list are helpful enough to mention when things you *can* do aren't necessarily things you *want* to do. ;) Enjoy your explorations! Steve Jul 18 '05 #11

 P: n/a It's me wrote: Yes, Russell, what you suggested works. I have to chew more on the syntax to see how this is working. because in the book that I have, it says: exec code [ in globaldict [, localdict] ] The [] indicate the last two parts are optional. If you don't supply them, exec just uses the current namespace. However, as others have said, you are much better off using a separate dictionary for such values, rather than stuffing them into the local variables: user_vars = {} y = "a" user_vars[y] = 4 It keeps a clean separation between your variables and the user's variables, easily avoiding namespace conflicts. Cheers, Nick. -- Nick Coghlan | nc******@email.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.skystorm.net Jul 18 '05 #12

 P: n/a Caleb Hattingh wrote: '>>> a # The value of a is changed. 8 '>>> The value of a is changed. . . *maybe*. The Python language definition states explicitly that updates to the dictionary returned by locals() may not actually alter the local variables. Generally, altering the contents of the dicts returned by locals() and globals() is unreliable at best. Cheers, Nick. -- Nick Coghlan | nc******@email.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.skystorm.net Jul 18 '05 #13

 P: n/a Nick Coghlan wrote: Generally, altering the contents of the dicts returned by locals() and globals() is unreliable at best. Nick, could you please comment on why you say this about globals()? I've never heard of any possibility of "unreliability" in updating globals() and, as far as I know, a large body of code exists which does in fact rely on this -- much of mine included. ;-) -Peter Jul 18 '05 #14

 P: n/a Peter Hansen wrote: Nick Coghlan wrote: Generally, altering the contents of the dicts returned by locals() and globals() is unreliable at best. Nick, could you please comment on why you say this about globals()? I've never heard of any possibility of "unreliability" in updating globals() and, as far as I know, a large body of code exists which does in fact rely on this -- much of mine included. ;-) Updating locals() is unreliable. Updating globals() is fine, AFAIK. http://docs.python.org/lib/built-in-funcs.html I believe that the only time that locals() is updatable is when locals() is globals(): locals() is globals() True x Traceback (most recent call last): File "", line 1, in ? NameError: name 'x' is not defined locals()['x'] = 3 x 3 def f(): .... print locals() is globals() .... locals()['x'] = 3 .... print x .... f() False Traceback (most recent call last): File "", line 1, in ? File "", line 4, in f NameError: global name 'x' is not defined Steve Jul 18 '05 #15

 P: n/a Peter, I second that. Nick In what way is it unreliable? I can't seem to create a situation where the update through globals and locals doesn't work. Are you referring perhaps to the possibility of variables being garbage collected and then not being around later when one tries to access them through a string name? I don't know very much about the garbage collector, so I can't say for sure. thx Caleb On Wed, 08 Dec 2004 10:38:30 -0500, Peter Hansen wrote: Nick Coghlan wrote: Generally, altering the contents of the dicts returned by locals() and globals() is unreliable at best. Nick, could you please comment on why you say this about globals()? I've never heard of any possibility of "unreliability" in updating globals() and, as far as I know, a large body of code exists which does in fact rely on this -- much of mine included. ;-) -Peter Jul 18 '05 #16

 P: n/a Caleb Hattingh wrote: In what way is it unreliable?**I*can't*seem*to*create*a*situation*wh ere the update through globals and locals doesn't work.***Are*you*referring Updates to a locals() dictionary may not be reflected by the variables in the local scope, e. g.: def f(): .... locals()["a"] = 1 .... print a .... f() Traceback (most recent call last): File "", line 1, in ? File "", line 3, in f NameError: global name 'a' is not defined def f(): .... a = 42 .... locals()["a"] = 1 .... print a .... f() 42 Updating globals() should be safe. Peter Jul 18 '05 #17

 P: n/a Steve, I don't think I understand. Here is what I just tried: '>>> def f(): x = 3 d = locals() print x print d['x'] d['x'] = 5 print x '>>> f() 3 3 3 '>>> In your example, x had not yet been initialised, maybe. What I am seeing is that "x" does not seem to update when being assigned to - I guess this is what you are referring to by being unreliable. But "unreliable" sounds kinda vague and intermittent, and I assume that is not the case here - What is the Rule(tm)? Thanks Caleb On Wed, 08 Dec 2004 16:59:23 GMT, Steven Bethard wrote: Peter Hansen wrote: Nick Coghlan wrote: Generally, altering the contents of the dicts returned by locals() and globals() is unreliable at best. Nick, could you please comment on why you say this about globals()? I've never heard of any possibility of "unreliability" in updating globals() and, as far as I know, a large body of code exists which does in fact rely on this -- much of mine included. ;-) Updating locals() is unreliable. Updating globals() is fine, AFAIK. http://docs.python.org/lib/built-in-funcs.html I believe that the only time that locals() is updatable is when locals() is globals(): >>> locals() is globals() True >>> x Traceback (most recent call last): File "", line 1, in ? NameError: name 'x' is not defined >>> locals()['x'] = 3 >>> x 3 >>> def f(): ... print locals() is globals() ... locals()['x'] = 3 ... print x ... >>> f() False Traceback (most recent call last): File "", line 1, in ? File "", line 4, in f NameError: global name 'x' is not defined Steve Jul 18 '05 #18

 P: n/a Caleb Hattingh wrote: Steve, I don't think I understand. Here is what I just tried: '>>> def f(): x = 3 d = locals() print x print d['x'] d['x'] = 5 print x '>>> f() 3 3 3 '>>> In your example, x had not yet been initialised, maybe. What I am seeing is that "x" does not seem to update when being assigned to - I guess this is what you are referring to by being unreliable. Yes, that was my intent. In the same way that my "x" was not initialized, your "x" is not updated. locals() is readable but not writable in any case where locals() is not globals(), I believe. But "unreliable" sounds kinda vague and intermittent, and I assume that is not the case here - What is the Rule(tm)? Unfortunately, I don't think there is a Rule(tm) because the behavior of locals() (and globals()?) are implementation details. I remember hearing an explanation of why locals() is not writable that had to do with something about efficiency and the call stack (or something like that)... Steve Jul 18 '05 #19

 P: n/a Thx Peter I verified this situation myself with a post from Steven Bethard earlier (trying to use "locals" within a function definition). I am convinced now that locals() doesn't work as (I) expected. Steven says there was some or other reason why locals() as used in this context is not writable - Do you know why this is? I really do not like guidelines like "may not work", "is unreliable" and so on. Perhaps this is a character flaw, but I really do like to know what works, when it works, and when it doesn't work. In this scenario, we can see it doesn't work. To my eyes, it doesn't work *in the way I expect* (which is highly subjective, no argument there). Would this be a situation where it would be nice to have an exception thrown if locals() is assigned to in a scope where it is not writable? It would also be nice if globals and locals behaved the same, differing only in scope (which is what I expected originally anyway). But we can't have everything, I guess :) Caleb On Wed, 08 Dec 2004 20:49:53 +0100, Peter Otten <__*******@web.de> wrote: Caleb Hattingh wrote: In what way is it unreliable?Ã‚Â*Ã‚Â*IÃ‚Â*can'tÃ‚Â*seemÃ‚Â*toÃ‚Â*cre ateÃ‚Â*aÃ‚Â*situationÃ‚Â*where the update through globals and locals doesn't work.Ã‚Â*Ã‚Â*Ã‚Â*AreÃ‚Â*youÃ‚Â*referring Updates to a locals() dictionary may not be reflected by the variables in the local scope, e. g.: def f(): ... locals()["a"] = 1 ... print a ... f() Traceback (most recent call last): File "", line 1, in ? File "", line 3, in f NameError: global name 'a' is not defined def f(): ... a = 42 ... locals()["a"] = 1 ... print a ... f() 42 Updating globals() should be safe. Peter Jul 18 '05 #20

 P: n/a Caleb Hattingh wrote: I am convinced now that locals() doesn't work as (I) expected. Steven says there was some or other reason why locals() as used in this context is not writable - Do you know why this is? I really do not like guidelines like "may not work", "is unreliable" and so on. Perhaps this is a character flaw, but I really do like to know what works, when it works, and when it doesn't work. Those who've talked about it being "unreliable" are misstating the Rule that you are looking for. I'll quote it below, so that you aren't left in this unfortunate state of limbo: The Rule of locals() Updating locals() should not be done. Treat the return value of locals() as read-only. Never try to update it. End of story. Anything that appears to suggest that locals() might sometimes actually be writable is not really happening. Look the other way. Pay no attention to the man behind the curtain. And especially, whatever else you do, don't let the PSU se Jul 18 '05 #21

 P: n/a Steven Bethard wrote: I remember hearing an explanation of why locals() is not writable that had to do with something about efficiency and the call stack (or something like that)... IIRC, the function local namespace (in CPython) is kept internally as a static array, rather than as a dictionary, which dramatically speeds (function-local) name lookups. However, this also means that all local names must be determinable at function-definition time. In contrast, the global namespace is a true Python dictionary. Where globals() returns a reference to that dictionary, locals() (when locals() is not globals()) constructs a separate dictionary from the static array containing the local namespace. In effect, globals() gives a reference while locals() gives a copy, with standard Python reference/copy semantics applying. (Note also that functions which use exec cannot use the static namespace optimization, and thus tend to be *much* slower than normal functions (in addition to being a huge security problem). I don't know, however, whether locals() can update the local namespace in such un-optimized functions. Whether it actually does so or not, relying on such special-case behavior would be extremely foolish to do...) Of course, I'm just going off of what I remember having been said elsewhere on c.l.p., and I wouldn't recommend anyone betting their life savings on the reliability of my memory... :) Jeff Shannon Technician/Programmer Credit International Jul 18 '05 #22

 P: n/a Jeff Shannon wrote: (Note also that functions which use exec cannot use the static namespace optimization, and thus tend to be *much* slower than normal functions (in addition to being a huge security problem). I don't know, however, whether locals() can update the local namespace in such un-optimized functions. Doesn't look like it: exec """\ .... def f(): .... x = 3 .... locals()['x'] = 4 .... print x .... """ f() 3 Steve Jul 18 '05 #23

 P: n/a Jeff Shannon wrote: Note also that functions which use exec cannot use the static namespace optimization, and thus tend to be *much* slower than normal functions In what circumstances will this be true? I couldn't verify it: cat fib.py def fib1(n): a, b = 0, 1 while True: a, b = b, a + b yield a exec """\ def fib2(n): a, b = 0, 1 while True: a, b = b, a + b yield a """ python -m timeit -s "import fib" "fib.fib1(100)" 1000000 loops, best of 3: 0.714 usec per loop python -m timeit -s "import fib" "fib.fib2(100)" 1000000 loops, best of 3: 0.705 usec per loop Jul 18 '05 #24

 P: n/a Steven Bethard wrote: Jeff Shannon wrote: Note also that functions which use exec cannot use the static namespace optimization, and thus tend to be *much* slower than normal functions In what circumstances will this be true? I couldn't verify it: [...] exec """\ def fib2(n): a, b = 0, 1 while True: a, b = b, a + b yield a """ I was referring to functions which have an internal exec statement, not functions which are created entirely within an exec -- i.e., something like this: def fib3(n): a, b = 0, 1 while True: exec "a, b = b, a + b" yield a In your fib2(), when the function is defined, the entire contents of the local namespace can be determined (it's just that the function isn't "defined" until the exec statement is executed). In fib3(), when the function is defined, the parser can't determine what's happening inside the exec statement (it just sees a string, and that string may depend on other runtime circumstances which will happen latter), so it can't say for certain whether names other than a and b are created. (Consider the case where the string to be exec'ed is passed in as a function argument...) Jeff Shannon Technician/Programmer Credit International Jul 18 '05 #25

 P: n/a To respond to and summarize several posts in this discussion: Within a function, where the local namespace is distinct from the global (module) namespace, CPython usually implements the local namespace internally as a fixed-length array. When this is true, locals() is a *copy* of the local namespace and not the namespace itself. Once that dict is created, the history of how it was created is immediately forgotten, just as with any other ordinary Python dict. That dict can be bound to a name or other target and modified like any other dict, and there could be reasons to do so. However, modifying it has no more effect on the local namespace than modifying any other local dict. Terry J. Reedy Jul 18 '05 #26

 P: n/a Jeff Shannon wrote: Steven Bethard wrote: Jeff Shannon wrote: Note also that functions which use exec cannot use the static namespace optimization, and thus tend to be *much* slower than normal functions In what circumstances will this be true? I couldn't verify it: [snip] I was referring to functions which have an internal exec statement, not functions which are created entirely within an exec -- i.e., something like this: Thanks for the clarification. Here's the results for some functions with internal exec statements: cat fib.py def fib1(n): a, b = 0, 1 while True: a, b = b, a + b yield a exec """\ def fib2(n): a, b = 0, 1 while True: a, b = b, a + b yield a """ def fib3(n): a, b = 0, 1 while True: exec "a, b = b, a + b" yield a def fib4(n): exec "a, b = 0, 1" while True: exec "a, b = b, a + b" yield a python -m timeit -s "import fib" "fib.fib1(100)" 1000000 loops, best of 3: 0.71 usec per loop python -m timeit -s "import fib" "fib.fib2(100)" 1000000 loops, best of 3: 0.678 usec per loop python -m timeit -s "import fib" "fib.fib3(100)" 1000000 loops, best of 3: 0.826 usec per loop python -m timeit -s "import fib" "fib.fib4(100)" 1000000 loops, best of 3: 0.821 usec per loop I'm not sure I'd say they're *much* slower, but you're right; they're definitely slower. Steve Jul 18 '05 #27

 P: n/a Peter Hansen wrote: Caleb Hattingh wrote: I am convinced now that locals() doesn't work as (I) expected. Steven says there was some or other reason why locals() as used in this context is not writable - Do you know why this is? I really do not like guidelines like "may not work", "is unreliable" and so on. Perhaps this is a character flaw, but I really do like to know what works, when it works, and when it doesn't work. Those who've talked about it being "unreliable" are misstating the Rule that you are looking for. I'll quote it below, so that you aren't left in this unfortunate state of limbo: The Rule of locals() Updating locals() should not be done. Treat the return value of locals() as read-only. Never try to update it. End of story. Anything that appears to suggest that locals() might sometimes actually be writable is not really happening. Look the other way. Pay no attention to the man behind the curtain. And especially, whatever else you do, don't let the PSU se I agree. But much of the confusion stems from interpreter experiments like locals()["a"] = 42 a 42 That would go away if locals() returned an ignore-write proxy where the global and local scope are identical. The ability to "just try it" is an asset. Peter Jul 18 '05 #28

 P: n/a Caleb Hattingh wrote: I am convinced now that locals() doesn't work as (I) expected. Steven says there was some or other reason why locals() as used in this context is not writable - Do you know why this is? I really do not like guidelines like "may not work", "is unreliable" and so on. Perhaps this is a character flaw, but I really do like to know what works, when it works, and when it doesn't work. I think Peter Hansen has answered that. Your expectations were just wrong. In this scenario, we can see it doesn't work. To my eyes, it doesn't work *in the way I expect* (which is highly subjective, no argument there). Would this be a situation where it would be nice to have an exception thrown if locals() is assigned to in a scope where it is not writable? If python were to throw an exception, it should always be thrown. But I'm the wrong one to worry about that as I didn't even find a single globals()[name] = value assignment in my scripts. I want to know a variable's name, or I put it in a dictionary. It would also be nice if globals and locals behaved the same, differing only in scope (which is what I expected originally anyway). But we can't have everything, I guess :) That would mean that both would become read-only, I guess, but I don't see that happen. Peter Jul 18 '05 #29

 P: n/a Peter Hansen wrote: Nick Coghlan wrote: Generally, altering the contents of the dicts returned by locals() and globals() is unreliable at best. Nick, could you please comment on why you say this about globals()? I've never heard of any possibility of "unreliability" in updating globals() and, as far as I know, a large body of code exists which does in fact rely on this -- much of mine included. ;-) As Steve pointed out, I was, well, flat out wrong. You're quite correct - it's only locals() that can cause a problem. Cheers, Nick. -- Nick Coghlan | nc******@email.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.skystorm.net Jul 18 '05 #30

 P: n/a Both Peters :) Sure, I must concede that the problem here was my expectation of how things should work. Thanks for the explanations. I still don't really know whether this behaviour of locals() is the result of a design decision, or an implementation artifact of CPython, but at least I have a clear idea of how to play nice with locals(). thx Caleb Peter Otten wrote: Caleb Hattingh wrote: I am convinced now that locals() doesn't work as (I) expected. Steven says there was some or other reason why locals() as used in this context is not writable - Do you know why this is? I really do not like guidelines like "may not work", "is unreliable" and so on. Perhaps this is a character flaw, but I really do like to know what works, when it works, and when it doesn't work. I think Peter Hansen has answered that. Your expectations were just wrong. In this scenario, we can see it doesn't work. To my eyes, it doesn't work *in the way I expect* (which is highly subjective, no argument there). Would this be a situation where it would be nice to have an exception thrown if locals() is assigned to in a scope where it is not writable? If python were to throw an exception, it should always be thrown. But I'm the wrong one to worry about that as I didn't even find a single globals()[name] = value assignment in my scripts. I want to know a variable's name, or I put it in a dictionary. It would also be nice if globals and locals behaved the same, differing only in scope (which is what I expected originally anyway). But we can't have everything, I guess :) That would mean that both would become read-only, I guess, but I don't see that happen. Peter Jul 18 '05 #31

 P: n/a On Tue, 07 Dec 2004 21:12:24 GMT, "It's me" wrote: "Caleb Hattingh" wrote in messagenews:op**************@news.telkomsa.net... Hi It's me > > a = 3 > y = "a" > print eval(y) > To get 'a' to be 4 here, you would say a = 4Obviously but that's not what I wish to do. I am not sure why you would want to do otherwise? Perhaps you could sketch out a little more about what you are trying to do? That would help a lot. Are you aiming for something like pointer emulation with simple datatypes?In REXX, for instance, one can do a: interpret y' = 4'Since y contains a, then the above statement amongs to: a = 4There are many situations where this is useful. For instance, you might begetting an input which is a string representing the name of a variable andyou wish to evaluate the expression (like a calculator application, forinstance). If you want to make a calculator, why not define a calculator class that behaves the way you like, giving it methods for interaction according to any syntax you like? What would you like to be able to type for your calculator to interpret? assignment statements and expressions? There is a difference between the statements your calculator interprets and the statements you use to implement your calculator, unless you are hoping just to pass input through for Python to interpret (which will be risky if you don't control what's entered!). But, to pursue your REXX example a bit, the question IMO is how important the spelling is to you vs the functionality. Python lets you create custom objects that behave pretty much any way you like. You can (ab)use the way python compiles various operators operating on or with instances of your custom objects so you can spell things in various ways, e.g., instead of a = 3 y = "a" print eval(y) you could have a magic class instance o and write o.a = 3 o.y = "a" print o().y and instead of interpret y' = 4' write o().y = 4 Let's try it (untested beyond what you see here ;-) class Magic(object): ... def __call__(self): ... return DerefName(self) ... class DerefName(object): ... def __init__(self, wrapped): ... object.__setattr__(self, 'wrapped', wrapped) ... def __getattr__(self, name): ... wrapped = object.__getattribute__(self, 'wrapped') ... return getattr(wrapped, getattr(wrapped, name)) ... def __setattr__(self, name, value): ... wrapped = object.__getattribute__(self, 'wrapped') ... setattr(wrapped, getattr(wrapped, name), value) ... o = Magic() o.a = 3 o.y = "a" print o().y 3 o().y = 4 print o().y 4 o.y 'a' o.a 4 o().z Traceback (most recent call last): File "", line 1, in ? File "", line 6, in __getattr__ AttributeError: 'Magic' object has no attribute 'z' o.z = "y" o().z 'a' o.z 'y' Anyway, getattr/setattr functionality provides the primal cauldron for python magic, if you want to cook something up, and incantations usually involve prefixing the name of a magic instance to your spell(ing)s ;-) Add descriptors for extra spice ... Double, double, toil and trouble... oh, wait, that's for floating point ;-) Regards, Bengt Richter Jul 18 '05 #32

 P: n/a Nick Coghlan wrote: Peter Hansen wrote: Nick, could you please comment on why you say this about globals()? I've never heard of any possibility of "unreliability" in updating globals() and, as far as I know, a large body of code exists which does in fact rely on this -- much of mine included. ;-) As Steve pointed out, I was, well, flat out wrong. You're quite correct - it's only locals() that can cause a problem. Of course, just because modifications of the dict returned by globals() *do* reliably result in modifications to the global namespace, doesn't mean it's a good idea. ;) Personally, I don't *want* to create variables by "magic" like that. I'd rather pass a few extra parameters around, and explicitly create any global names I need. If I really need to store objects under arbitrary names, then I probably should be using a regular dict (and passing it around as need be) instead of dumping stuff into globals(). (But then, I'm a devoted follower of the Pythonic principle of 'explicit is better than implicit' -- heck, even before I knew Python existed, I typically used this->name to reference C++ members despite the fact that 'this' was not required, just because I wanted to be able to *see* which variables were members and which weren't...) Jeff Shannon Technician/Programmer Credit International Jul 18 '05 #33

 P: n/a Jeff Shannon wrote: Of course, just because modifications of the dict returned by globals() *do* reliably result in modifications to the global namespace, doesn't mean it's a good idea. ;) "The" global namespace misses the possibility that doing this in "a" global namespace might be a good idea. For example, in the namespace of a special module intended to be used as a convenient way of accessing global information. See below. Personally, I don't *want* to create variables by "magic" like that. I'd rather pass a few extra parameters around, and explicitly create any global names I need. If I really need to store objects under arbitrary names, then I probably should be using a regular dict (and passing it around as need be) instead of dumping stuff into globals(). The main way I use this is in some sort of a "const" module, which provides access to a large set of constant information. In other words, in contrast to what you had in mind when you wrote the above, I'm dealing with neither "variables" nor information that _would_ best be put in a dict. The last time I did this I had a .h header file from C which I wanted to wrap up for Python. Rather than convert once, statically, I had a const.py module which loaded the .h file contents and converted all lines which it recognized (mostly lines of the form "#define XXX nnn") into Python names stuck into that module's globals(). Other modules just do "import const" and then things like "const.DAQmx_Val_Volts" to get access to any of the over 1700 defined values. In general I would say that mucking with globals() like this is probably best restricted to constants like in this case, if at all. -Peter Jul 18 '05 #34

 P: n/a Jeff I do the same thing in Delphi -> prepend "Self" before all the members in class methods even though its not required. I do it partially for the same reason as you - so I can grok which variables are local and which are global (well, global within the class, anyway). The other reason is because of the magical little menu that pops up when I type the period after "Self", and lets me pick a class member by typing the first few letters... Keep well Caleb On Thu, 09 Dec 2004 09:39:58 -0800, Jeff Shannon wrote: -- heck, even before I knew Python existed, I typically used this->name to reference C++ members despite the fact that 'this' was not required, just because I wanted to be able to *see* which variables were members and which weren't...) Jeff Shannon Technician/Programmer Credit International Jul 18 '05 #35

 P: n/a On Wed, 8 Dec 2004 20:22:52 -0500, "Terry Reedy" wrote: To respond to and summarize several posts in this discussion:Within a function, where the local namespace is distinct from the global(module) namespace, CPython usually implements the local namespaceinternally as a fixed-length array. When this is true, locals() is a*copy* of the local namespace and not the namespace itself. Once that dictis created, the history of how it was created is immediately forgotten,just as with any other ordinary Python dict.That dict can be bound to a name or other target and modified like anyother dict, and there could be reasons to do so. However, modifying it hasno more effect on the local namespace than modifying any other local dict. It doesn't appear to be _quite_ ordinary though (note that print d['x'] inside does print 3 the first time and 5 after the d['x']=5 assignment, but is not returned in d when d returns in the results): I think I'd rather locals() totally refuse updates than allow retrievable updates in a way that leaves me wondering what kind of object it is and what happens to it when it is exported from a function (some kind of closure stuff involved in converting a proxy to a dict? (will speculation)) ;-/ def f(): ... x = 3 ... d = locals() ... D = dict(locals()) ... print 'x', x ... print "d['x']",d['x'] ... d['x'] = 5 ... print 'x', x ... print "d['x']",d['x'] ... print "D['x']", D['x'] ... D['x'] = 7 ... print "d['x']",d['x'] ... print "D['x']", D['x'] ... return d, D, locals() ... d,D,L = f() x 3 d['x'] 3 x 3 d['x'] 5 D['x'] 3 d['x'] 5 D['x'] 7 d {'x': 3, 'd': {...}, 'D': {'x': 7, 'd': {...}}} D {'x': 7, 'd': {'x': 3, 'd': {...}, 'D': {...}}} L {'x': 3, 'd': {...}, 'D': {'x': 7, 'd': {...}}} L['d']['x'] # not 5 3 L['D']['x'] # is 7 7 d['x'] 3 D['x'] 7 Regards, Bengt Richter Jul 18 '05 #36

 P: n/a Peter Hansen wrote: The main way I use this is in some sort of a "const" module, which provides access to a large set of constant information. In other words, in contrast to what you had in mind when you wrote the above, I'm dealing with neither "variables" nor information that _would_ best be put in a dict. [...] In general I would say that mucking with globals() like this is probably best restricted to constants like in this case, if at all. Indeed, for almost every rule, there are exceptions.. Legitimate cases also exist for using eval() and exec, though in general both of those are better avoided. The case you describe does sound like a legitimate use of writing to globals(), with realistic expectations of the costs and benefits (Actually, in your provided example, I might have const.py parse the header file into a dict named const, and then have my modules use 'from const import const'. But I will admit that the extra complication on import may not be worth the "cleaner" module internals... As always, it's a tradeoff, and each programmer must decide which costs are worth bearing in their particular situation.) Jeff Shannon Technician/Programmer Credit International Jul 18 '05 #37

 P: n/a Peter Hansen wrote: In general I would say that mucking with globals() like this is probably best restricted to constants like in this case, if at all. Modifying globals() not even necessary for this. When I want to dynamically update the global namespace, I do it this way: mod = __import__(__name__) setattr(mod,symbol,value) Works perfectly unless you're worried about someone modifying the built in __import__. -- CARL BANKS Jul 18 '05 #38

 P: n/a In article <5SPtd.210910\$HA.146444@attbi_s01>, Steven Bethard wrote:Jeff Shannon wrote: I was referring to functions which have an internal exec statement, not functions which are created entirely within an exec -- i.e., something like this:Thanks for the clarification. Here's the results for some functionswith internal exec statements: cat fib.pydef fib1(n): a, b = 0, 1 while True: a, b = b, a + b yield a exec """\def fib2(n): a, b = 0, 1 while True: a, b = b, a + b yield a"""def fib3(n): a, b = 0, 1 while True: exec "a, b = b, a + b" yield adef fib4(n): exec "a, b = 0, 1" while True: exec "a, b = b, a + b" yield a python -m timeit -s "import fib" "fib.fib1(100)"1000000 loops, best of 3: 0.71 usec per loop python -m timeit -s "import fib" "fib.fib2(100)"1000000 loops, best of 3: 0.678 usec per loop python -m timeit -s "import fib" "fib.fib3(100)"1000000 loops, best of 3: 0.826 usec per loop python -m timeit -s "import fib" "fib.fib4(100)"1000000 loops, best of 3: 0.821 usec per loopI'm not sure I'd say they're *much* slower, but you're right; they'redefinitely slower. The thing is, that once you drop local-namespace optimization, the entire function gets slowed down, possibly by 40%: def fib5 (n): a, b, i = 0, 1, n while i > 0: a, b = b, a+b yield a i -= 1 def fib6 (n): exec "a, b, i = 0, 1, n" while i > 0: a, b = b, a+b yield a i -= 1 f:\home\mwilson\projects\python>python e:\bin\python23\lib\timeit.py -s "import fib" "[i for i in fib.fib5(100)]" 1000 loops, best of 3: 1.95e+003 usec per loop f:\home\mwilson\projects\python>python e:\bin\python23\lib\timeit.py -s "import fib" "[i for i in fib.fib6(100)]" 100 loops, best of 3: 2.82e+003 usec per loop Regards. Mel. Jul 18 '05 #39

 P: n/a Mel Wilson wrote: The*thing*is,*that*once*you*drop*local-namespace optimization, the entire function gets slowed down, possibly by 40%: It's not that bad as most of the extra time is spend on compiling the string. def fib5(n): a, b, i = 0, 1, n while i > 0: a, b = b, a+b yield a i -= 1 def fib6(n): exec "a, b, i = 0, 1, n" while i > 0: a, b = b, a+b yield a i -= 1 def fib7(n, c=compile("a, b, i = 0, 1, n", "", "exec")): exec c while i > 0: a, b = b, a+b yield a i -= 1 [Python 2.3] \$ timeit.py -s"from fib import fib5 as fib" "list(fib(100))" 10000 loops, best of 3: 143 usec per loop \$ timeit.py -s"from fib import fib6 as fib" "list(fib(100))" 10000 loops, best of 3: 208 usec per loop \$ timeit.py -s"from fib import fib7 as fib" "list(fib(100))" 10000 loops, best of 3: 151 usec per loop Peter Jul 18 '05 #40

 P: n/a Carl Banks wrote: Modifying globals() not even necessary for this. When I want to dynamically update the global namespace, I do it this way: mod = __import__(__name__) setattr(mod,symbol,value) Works perfectly unless you're worried about someone modifying the built in __import__. Well, aside from the detail that modifying a module's contents via a reference to that module is far more evil than playing with globals() ;) Even if that module is the one you're running in. . . Cheers, Nick. -- Nick Coghlan | nc******@email.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.skystorm.net Jul 18 '05 #41

 P: n/a In article , Peter Otten <__*******@web.de> wrote:Mel Wilson wrote: The*thing*is,*that*once*you*drop*local-namespace optimization, the entire function gets slowed down, possibly by 40%:It's not that bad as most of the extra time is spend on compiling thestring. [ ... ]def fib7(n, c=compile("a, b, i = 0, 1, n", "", "exec")): exec c [ ... ] ! Regards. Mel. Jul 18 '05 #42

 P: n/a Nick Coghlan wrote: Well, aside from the detail that modifying a module's contents via a reference to that module is far more evil than playing with globals() ;) Even if that module is the one you're running in. . . It seems to me that that which makes modifying a module's contents via a reference evil makes modifying them via globals() equally evil. The only thing is, modifying them through a module reference is explicit and straightforward, whereas modifying the contents via globals() is an implicit, backhanded trick that relies on certain behind-the-scenes behavior. I'd say using globals() is far eviler. So I must disagree with your good-natured objection. Unless there's some practical weakness of using references that I am unaware of. -- CARL BANKS (Yes, I know eviler is not a word.) Jul 18 '05 #43

 P: n/a Carl Banks wrote: Nick Coghlan wrote:to that module is far more evil than playing with globals() ;) I'd say using globals() is far eviler. I don't understand either of you. ;-) From my point of view, they're basically identical, and although I find Carl's approach slightly less explicit and harder to read (mainly the uncommon __import__ call, but it's not a big deal), I can't see why either of them would be considered evil. Changing a module's contents via globals() is a very common and surely benign thing to do. -Peter Jul 18 '05 #44

 P: n/a > From my point of view, they're basically identical, and although I find Carl's approach slightly less explicit and harder to read (mainly the uncommon __import__ call, but it's not a big deal), I can't see why either of them would be considered evil. Of course, when I said evil, I didn't mean evil, I meant Evil(tm). I suspect Nick meant so as well. Personally, I just think __import__(__name__) is a bit more honest than globals() for a simple reason. What are you doing? You're changing module attributes. Well, here's the module object. You're using setattr on the module object to set module attributes. What are you doing? You're changing module attributes. Well, here's the module's dict. You're using dictionary access on the modules dict to set modules attributes. It's a bit more honest to set module attributes using setattr than dict access, I would say. That's why I prefer it. I admit, it's pretty weak. (But then again, so is __import__ being uncommon. :) It's not a big deal which you choose, as you say. Although I don't use globals() in this way, I do modify object dicts to get the effect of changing object attributes from time to time (mostly to take advantage of dict methods, which I could see being a reason to use globals() as well). -- CARL BANKS Jul 18 '05 #45

 P: n/a Carl Banks wrote: It's a bit more honest to set module attributes using setattr than dict access, I would say. Granted. But I think it's also more honest to change a module's dict by using globals() than by using a setattr call. <0.500 wink> -Peter Jul 18 '05 #46

### This discussion thread is closed

Replies have been disabled for this discussion.

### Similar topics

Browse more Python Questions on Bytes