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

Discussion in 'Python' started by It's me, Dec 7, 2004.

  1. It's me

    It's me Guest

    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
    It's me, Dec 7, 2004
    #1
    1. Advertising

  2. It's me

    It's me Guest

    "Caleb Hattingh" <> wrote in message
    news:eek:...
    > 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
    It's me, Dec 7, 2004
    #2
    1. Advertising

  3. It's me

    Russell Blau Guest

    "It's me" <> wrote in message
    news:Y0ptd.39767$...
    >
    > 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.
    Russell Blau, Dec 7, 2004
    #3
  4. 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 && && 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
    Erik Max Francis, Dec 7, 2004
    #4
  5. It's me

    Craig Ringer Guest

    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
    Craig Ringer, Dec 7, 2004
    #5
  6. 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
    Steven Bethard, Dec 7, 2004
    #6
  7. It's me

    It's me Guest

    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:...
    > "It's me" <> wrote in message
    > news:Y0ptd.39767$...
    > >
    > > 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.
    >
    >
    It's me, Dec 7, 2004
    #7
  8. It's me

    It's me Guest

    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" <> 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
    It's me, Dec 7, 2004
    #8
  9. 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
    Steven Bethard, Dec 7, 2004
    #9
  10. 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
    Caleb Hattingh, Dec 8, 2004
    #10
  11. 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).
    Caleb Hattingh, Dec 8, 2004
    #11
  12. It's me

    Nick Coghlan Guest

    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 | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
    Nick Coghlan, Dec 8, 2004
    #12
  13. It's me

    Nick Coghlan Guest

    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 | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
    Nick Coghlan, Dec 8, 2004
    #13
  14. It's me

    Peter Hansen Guest

    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
    Peter Hansen, Dec 8, 2004
    #14
  15. updating locals() and globals() (WAS: How do I do this? (eval() onthe left hand side))

    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
    Steven Bethard, Dec 8, 2004
    #15
  16. It's me

    Peter Otten Guest

    Caleb Hattingh wrote:

    > 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


    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
    Peter Otten, Dec 8, 2004
    #16
  17. Re: updating locals() and globals() (WAS: How do I do this? (eval()on the left hand side))

    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
    Steven Bethard, Dec 8, 2004
    #17
  18. It's me

    Peter Hansen Guest

    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
    Peter Hansen, Dec 8, 2004
    #18
  19. It's me

    Jeff Shannon Guest

    Re: updating locals() and globals() (WAS: How do I do this? (eval()on the left hand side))

    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
    Jeff Shannon, Dec 8, 2004
    #19
  20. Re: updating locals() and globals() (WAS: How do I do this? (eval()on the left hand side))

    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
    Steven Bethard, Dec 9, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kim André Akerø

    Left-hand menu in CSS

    Kim André Akerø, Jun 4, 2004, in forum: HTML
    Replies:
    7
    Views:
    3,164
    Beauregard T. Shagnasty
    Jun 7, 2004
  2. Bosconian
    Replies:
    1
    Views:
    1,365
    Bosconian
    May 9, 2006
  3. =?Utf-8?B?YnJ1bm8=?=

    Left and Right hand splitting and resizing

    =?Utf-8?B?YnJ1bm8=?=, Sep 15, 2006, in forum: ASP .Net
    Replies:
    5
    Views:
    4,141
    Walter Wang [MSFT]
    Sep 21, 2006
  4. Simon

    Outlook style left hand menu bar

    Simon, May 30, 2007, in forum: ASP .Net
    Replies:
    1
    Views:
    686
    bruce barker
    May 30, 2007
  5. Nishu
    Replies:
    3
    Views:
    756
    Peter Nilsson
    May 4, 2011
Loading...

Share This Page