2

How does eval() change the dict? This is an example: create a dict -> print -> eval -> print

>>> a={'a':'a','b':'b'}
>>> print(a)
{'a': 'a', 'b': 'b'}
>>> eval('a == "a"',a)
True
>>> print(a)
{'a': 'a', '__builtins__': {'bytearray': <class 'bytearray'>, 'IndexError': <class 'IndexError'>, 'all': <built-in function all>, 'help': Type help() for interactive help, or help(object) for help about object., 'vars': <built-in function vars>, 'SyntaxError': <class 'SyntaxError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'memoryview': <class 'memoryview'>, 'isinstance': <built-in function isinstance>, '__build_class__': <built-in function __build_class__>, 'copyright': Copyright (c) 2001-2012 Python Software Foundation.
All Rights Reserved.
...
xielingyun
  • 780
  • 9
  • 17
  • Obviusly, it does. Maybe the question should be changed into "How does...", "Why does..." or something like that. – glglgl Nov 21 '12 at 14:19

3 Answers3

4

The second argument to eval() is the globals used for the expression run by eval().

One of things python does when evaluating an expression is ensuring that the python built-ins are available to the evaluated expression, and to do that it adds the __builtins__ entry to that globals namespace.

So, yes, the eval() call did change your dictionary, and that is expected and normal behaviour. It even says so in the documentation for the function:

If the globals dictionary is present and lacks ‘__builtins__’, the current globals are copied into globals before expression is parsed. This means that expression normally has full access to the standard __builtin__ module and restricted environments are propagated.

If you want to avoid this change, use an empty dict for the globals, and use a as the locals namespace instead:

eval('a == "a"', {}, a)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • @xielingyun: you can look at the `exec` statement, but it's easier just to use `a` as the locals instead. Updated my answer. – Martijn Pieters Nov 21 '12 at 11:45
  • Note: [The doc say all globals are copied on `eval()`, but only `__builtins__` is copied](http://bugs.python.org/issue22057) – Ashwini Chaudhary Jun 02 '15 at 22:47
  • can anyone please tell in which order eval changes the dictionary. i mean does it sort ? – Cereal_Killer Oct 12 '15 at 08:58
  • @Cereal_Killer: `eval()` doesn't change dictionary order. Dictionary order is arbitrary and depends on the insertion and deletion history, see [Why is the order in Python dictionaries and sets arbitrary?](http://stackoverflow.com/q/15479928) – Martijn Pieters Oct 12 '15 at 13:42
2

The answer resides in the doc !

First of all, the second parameter to eval is the global dictionary. Than, we see:

If the globals dictionary is present and lacks ‘__builtins__’, the current globals are copied into globals before expression is parsed.

So yes, your dictionary gets modified by the call to eval.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
icecrime
  • 74,451
  • 13
  • 99
  • 111
  • @xielingyun Of course. Make a copy of your dict and give that into `eval()` and discard it. – glglgl Nov 21 '12 at 11:25
0

Yes it does. The second argument to eval() is the "globals" dictionary, which explains what you're seeing.

NPE
  • 486,780
  • 108
  • 951
  • 1,012