Author congma
Recipients bruno.loff, congma, docs@python, terry.reedy
Date 2021-03-27.11:18:02
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1616843884.18.0.658667425584.issue43605@roundup.psfhosted.org>
In-reply-to
Content
> sum(get(i) for i in range(len(l)))

This expression inside the body of ``func()`` references the name "get" and "l" (ell), both are local to the scope introduced by ``func()``. More specifically, these two names are referenced in the unnamed inner scope introduced by the generator-expression ``(get(i) for i in range(len(l)))``. It's as if you've passed into that inner scope the locals already introduced in func() by argument passing, e.g.

```
def func(...):
    get = ...
    ell = ...
    def genexpr(a, b):
        return <expression using a and b>
    sum(genexpr(get, ell))
```

> eval("get(0) + get(1) + get(2) + get(3)")

The expression in the string doesn't introduce its own scope. The name "get" is resolved because without additional arguments, eval() gets the locals from the calling scope's locals, which is where the name "get" came.

> eval("sum(get(i) for i in range(len(l)))", locals())

This tells eval() to use the calling scope's locals (the value returned by the call ``locals()``) as the globals for the evaluation of the expression in the string. When eval() executes the compiled code, it's as if that piece of code lives in an environment where names like "gets" and "l" (ell) are top-level. Therefore these names are resolved.

> eval("sum(get(i) for i in range(len(l)))")

Without explicitly telling eval() which globals/locals namespaces to use, eval() uses the current calling scope's. This is as if it were called like

eval("sum(get(i) for i in range(len(l)))", globals(), locals())

A problem arises. The generator expression in the string introduces an anonymous inner scope (let's call that scope "the box"). Inside the box, the name "i" is a local, there's no problem. But for the name "get", it's not local to the box, and it's not a global. Unlike other kinds of enclosed scope (for example, one introduced by an inner ``def`` block), "the box" has no way to look up names in enclosing scopes. This is the limitation referred to by the Language Reference's section on dynamic execution.

These are my attempts to explain why something works while others don't, based on my own understanding. I hope this helps somewhat, and if I made a mistake anywhere please correct them.
History
Date User Action Args
2021-03-27 11:18:04congmasetrecipients: + congma, terry.reedy, docs@python, bruno.loff
2021-03-27 11:18:04congmasetmessageid: <1616843884.18.0.658667425584.issue43605@roundup.psfhosted.org>
2021-03-27 11:18:04congmalinkissue43605 messages
2021-03-27 11:18:02congmacreate