[Python-ideas] Unpack of sequences

Guido van Rossum guido at python.org
Wed Aug 29 22:44:40 CEST 2012


On Wed, Aug 29, 2012 at 12:30 PM, M.-A. Lemburg <mal at egenix.com> wrote:
> Guido van Rossum wrote:
>> Also it won't work in Python 3.
>
> The star import is only used to trigger a call to PyFrame_LocalsToFast().
>
> In Python 3, the only way to trigger such a call is by using
> a call level trace function... or by exposing the C function
> in Python.

I don't believe that's the whole story. In Python 2, the import *
changes the semantics of locals. (So does 'exec' BTW.) Example:

>>> def f():
...  if 0: from test import *
...  locals()['x'] = 1
...  print(x)
...
<stdin>:1: SyntaxWarning: import * only allowed at module level
>>> def g():
...  locals()['x'] = 1
...  print(x)
...
>>> f()
1
>>> g()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in g
NameError: global name 'x' is not defined
>>>

Note the difference in generated bytecode:

>>> dis.dis(f)
  3           0 LOAD_CONST               1 (1)
              3 LOAD_NAME                0 (locals)
              6 CALL_FUNCTION            0
              9 LOAD_CONST               2 ('x')
             12 STORE_SUBSCR

  4          13 LOAD_NAME                1 (x)
             16 PRINT_ITEM
             17 PRINT_NEWLINE
             18 LOAD_CONST               0 (None)
             21 RETURN_VALUE
>>> dis.dis(g)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_GLOBAL              0 (locals)
              6 CALL_FUNCTION            0
              9 LOAD_CONST               2 ('x')
             12 STORE_SUBSCR

  3          13 LOAD_GLOBAL              1 (x)
             16 PRINT_ITEM
             17 PRINT_NEWLINE
             18 LOAD_CONST               0 (None)
             21 RETURN_VALUE
>>>

Compare line 13 in both: LOAD_NAME vs. LOAD_GLOBAL. Effectively, in
f(), the locals are dynamic (this is how they were implemented in
Python 0.0). In g() they are not, so the compiler decides that x can't
be a local, and generates a LOAD_GLOBAL.

In Python 3, all functions behave like g(): import * is no longer
allowed, and exec() is no longer treated special (it's no longer a
reserved keyword).

-- 
--Guido van Rossum (python.org/~guido)



More information about the Python-ideas mailing list