compiler package vs parser

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Fri Apr 17 17:10:43 CEST 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