By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,813 Members | 1,253 Online
Bytes IT Community
+ Ask a Question
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
Share this Question
Share on Google+
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" <ca****@telkomsa.net> 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" <it***@yahoo.com> 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" <ru******@hotmail.com> wrote in message
news:31*************@individual.net...
"It's me" <it***@yahoo.com> 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):

<prompt for name of variable in someother program space you wish to
retrieve>
<go retrieve the value from that other program>
<assign the retrieved value to a variable of the same name in Python>

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" <st************@gmail.com> 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):

<prompt for name of variable in someother program space you wish to
retrieve>
<go retrieve the value from that other program>
<assign the retrieved value to a variable of the same name in Python>
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 "<interactive input>", 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 "<interactive input>", line 1, in ?
File "<interactive input>", 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 <pe***@engcorp.com> 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 "<stdin>", line 1, in ?
File "<stdin>", 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
<st************@gmail.com> 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 "<interactive input>", 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 "<interactive input>", line 1, in ?
File "<interactive input>", 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 "<stdin>", line 1, in ?
File "<stdin>", 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" <it***@yahoo.com> wrote:

"Caleb Hattingh" <ca****@telkomsa.net> 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).

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 "<stdin>", line 1, in ?
File "<stdin>", 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 <je**@ccvcorp.com> 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" <tj*****@udel.edu> 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 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.

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 <st************@gmail.com> 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 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.


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", "<nofile>", "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 <cp*************@news.t-online.com>,
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 the
string.

[ ... ]def fib7(n, c=compile("a, b, i = 0, 1, n", "<nofile>", "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.