Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

eval fails to detect an iterating variable when evaluating a generator

Consider the following code:

print([a for a in [0] if eval("a in [0]")])
b = 0
print([b if eval("True in (x == b for x in [0])") else ''])
print([a for a in [0] if eval("True in (x == a for x in [0])")])

The output of this is:

[0]
[0]
Traceback (most recent call last):
  File "…", line 4, in <module>
    print([a for a in [0] if eval("False in (x == a for x in [0])")])
  File "…", line 4, in <listcomp>
    print([a for a in [0] if eval("False in (x == a for x in [0])")])
  File "<string>", line 1, in <module>
  File "<string>", line 1, in <genexpr>
NameError: name 'a' is not defined

The first eval uses the iterator a in a plain eval, and it works.

The second eval uses a static variable b when evaluating a generator, and it works.

The third eval combines the two ideas - it uses an iterator variable when evaluating a generator, and it fails to detect the variable and raises an error. Why does this happen?

like image 983
Dariush Avatar asked Dec 09 '25 11:12

Dariush


1 Answers

  • A genexp, like (x == a for x in [0]), creates its own scope.
  • So do list comprehensions, at least in Python 3.
  • Nested scopes inside an eval don't see variables from the locals used for the eval.

That means that in this line:

print([a for a in [0] if eval("True in (x == a for x in [0])")])

The a lookup inside the eval happens in a nested scope, so it doesn't see the a variable from the local variables of the scope where the eval occurred.

like image 167
user2357112 supports Monica Avatar answered Dec 11 '25 03:12

user2357112 supports Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!