compiler package vs parser
Gabriel Genellina
gagsl-py2 at yahoo.com.ar
Fri Apr 17 11:10:43 EDT 2009
En Fri, 17 Apr 2009 10:55:46 -0300, Scott David Daniels
<Scott.Daniels at acm.org> escribió:
> Robin Becker wrote:
>>
>> def func(D):
>> for k in D:
>> exec '%s=D[%r]' % (k,k)
>> print i, j, k
>> print locals()
>> print i, j, k
>> if __name__=='__main__':
>> func(dict(i=1,j=33))
>> #### end p.py
>> the compiler package ends up treating i & j as global, whereas the
>> modern analysis doesn't (and doesn't say they're definitely local
>> either).
>
> If they are not definitely local, they are non-local. Locals are
> determined at function definition time, not function execution time.
> So, your expectations about what the exec statement can do above are
> mistaken. You may try to work your way around it, but, IMHO, you
> will not succeed. If the code above were to work as you wish, every
> access to every non-local in code that contains an "exec" would have
> to check a "new locals" dictionary just in case the exec added a local.
And that's what happens. In absence of an exec statement, locals are
optimized: the compiler knows exactly how many of them exist, and its
names, just by static code analysis. But when the function contains an
exec statement (or an "import *" statement) this is not possible anymore,
and the compiler has to switch to another strategy and generate code using
a less-optimized approach. Unknown variables are accessed using
LOAD_NAME/STORE_NAME (require a name lookup) instead of the normal
LOAD_FAST/STORE_FAST for local variables and LOAD_GLOBAL/STORE_GLOBAL for
global ones.
> Think about what this code would have to do:
> > i = j = 42
> > def func(D):
> > print i, j, k
> > for k in D:
> > exec '%s=D[%r]' % (k,k)
> > print i, j, k
I don't completely understand what you wanted to show, but try this:
py> i = j = 42
py> def f():
... print i, j
... exec "k=1"
... print i, j, k
... exec "i=5"
... print i, j, k
...
py> f()
42 42
42 42 1
5 42 1
py> i
42
py> j
42
py> k
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'k' is not defined
Note that i starts as a global name and after the exec "i=5" it becomes a
local variable; and k is always a local variable even if there is no
explicit assignment to it (except in the exec).
--
Gabriel Genellina
More information about the Python-list
mailing list