[Python-Dev] Is outlawing-nested-import-* only an implementation issue?

Ka-Ping Yee ping@lfw.org
Thu, 22 Feb 2001 19:16:57 -0800 (PST)


  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.
  Send mail to mime@docserver.cac.washington.edu for more info.

--8323328-26770121-982898217=:4871
Content-Type: TEXT/PLAIN; charset=US-ASCII

On Thu, 22 Feb 2001, Ka-Ping Yee wrote:
>     - So what's the issue with not being able to determine
>       which variable binds in which scope?  With the model
>       just described, it's perfectly clear.  Is all this
>       breakage only caused by the particular optimizations
>       for lookup in the implementation (fast locals, etc.)?
>       Or have i missed something obvious?

That was poorly phrased.  To clarify, i am making the assumption
that the compiler wants each name to be associated with exactly
one scope per block in which it appears.

    1.  Is the assumption true?

    2.  If so, is this constraint motivated only by lookup optimization?

    3.  Why enforce this constraint when it would be inconsistent
        with behaviour that we already have at the top level?

If foo.py contains "x = 1", then this works at the top level:

        >>> if 1:                         # top level
        ...     x = 3
        ...     print x
        ...     from foo import *
        ...     def g(): print x
        ...     g()
        ...
        3
        1

I am suggesting that it should do exactly the same thing in a function:

        >>> def f():                      # x = 3 inside, no g()
        ...     x = 3
        ...     print x
        ...     from foo import *
        ...     print x
        ...
        >>> f()
        3
        1

        >>> def f():                      # x = 3 inside, nested g()
        ...     x = 3
        ...     print x
        ...     from foo import *
        ...     def g(): print x
        ...     g()
        ...
        >>> f()
        3
        1

        >>> x = 3
        >>> def f():                      # x = 3 outside, nested g()
        ...     print x
        ...     from foo import *
        ...     def g(): print x
        ...     g()
        ...
        >>> f()
        3
        1

(Replacing "from foo import *" above with "x = 1" or "exec('x = 1')"
should make no difference.   So this isn't just about internal-import-*
and exec-without-in, even if we do eventually deprecate internal-import-*
and exec-without-in -- which i would tend to support.)

Here is a summary of the behaviour i observe and propose.

                             1.5.2       2.1a1      suggested

    top level
        from foo import *     3,1         3,1          3,1
        exec('x = 1')         3,1         3,1          3,1
        x = 1                 3,1         3,1          3,1

    x = 3 outside, no g()
        from foo import *     3,1         3,1          3,1
        exec('x = 1')         3,1         3,1          3,1
        x = 1                  x      UnboundLocal     3,1

    x = 3 inside, no g()
        from foo import *     3,1         3,1          3,1
        exec('x = 1')         3,1         3,1          3,1
        x = 1                  x      UnboundLocal     3,1

    x = 3 outside, nested g()
        from foo import *     3,3     SyntaxError      3,1
        exec('x = 1')         3,3     SyntaxError      3,1
        x = 1                  x      UnboundLocal     3,1

    x = 3 inside, nested g()
        from foo import *     3,x     SyntaxError      3,1
        exec('x = 1')         3,x     SyntaxError      3,1
        x = 1                 3,x         3,1          3,1

(I don't know what the heck is going on in Python 1.5.2 in the
cases where it prints 'x'.)

My postulates are:

    1.  "exec('x = 1')" should behave exactly the same as "x = 1"

    2.  "from foo import *" should do the same as "x = 1"

    3.  "def g(): print x" should behave the same as "print x"


The testing script is attached.


-- ?!ng

--8323328-26770121-982898217=:4871
Content-Type: TEXT/PLAIN; charset=US-ASCII; name="scopetest.py"
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.10.10102221916570.4871@skuld.kingmanhall.org>
Content-Description: 
Content-Disposition: attachment; filename="scopetest.py"

aW1wb3J0IHN5cw0KDQpmaWxlID0gb3BlbignZm9vLnB5JywgJ3cnKQ0KZmls
ZS53cml0ZSgneCA9IDEnKQ0KZmlsZS5jbG9zZSgpDQoNCnRvcGxldmVsID0g
IiIiDQp4ID0gMw0KcHJpbnQgeA0KJXMNCmRlZiBnKCk6IHByaW50IHgNCmco
KQ0KIiIiDQoNCm91dHNpZGUgPSAiIiINCnggPSAzDQpkZWYgZigpOg0KICAg
IHByaW50IHgNCiAgICAlcw0KICAgIHByaW50IHgNCmYoKQ0KIiIiDQoNCmlu
c2lkZSA9ICIiIg0KeCA9IDMNCmRlZiBmKCk6DQogICAgcHJpbnQgeA0KICAg
ICVzDQogICAgcHJpbnQgeA0KZigpDQoiIiINCg0KbmVzdGVkb3V0c2lkZSA9
ICIiIg0KeCA9IDMNCmRlZiBmKCk6DQogICAgcHJpbnQgeA0KICAgICVzDQog
ICAgZGVmIGcoKTogcHJpbnQgeA0KICAgIGcoKQ0KZigpDQoiIiINCg0KbmVz
dGVkaW5zaWRlID0gIiIiDQpkZWYgZigpOg0KICAgIHggPSAzDQogICAgcHJp
bnQgeA0KICAgICVzDQogICAgZGVmIGcoKTogcHJpbnQgeA0KICAgIGcoKQ0K
ZigpDQoiIiINCg0KZm9yIHRlbXBsYXRlIGluIFt0b3BsZXZlbCwgb3V0c2lk
ZSwgaW5zaWRlLCBuZXN0ZWRvdXRzaWRlLCBuZXN0ZWRpbnNpZGVdOg0KICAg
IGZvciBzdGF0ZW1lbnQgaW4gWyJmcm9tIGZvbyBpbXBvcnQgKiIsICJleGVj
KCd4ID0gMScpIiwgInggPSAxIl06DQogICAgICAgIGNvZGUgPSB0ZW1wbGF0
ZSAlIHN0YXRlbWVudA0KICAgICAgICB0cnk6DQogICAgICAgICAgICBleGVj
IGNvZGUgaW4ge30NCiAgICAgICAgZXhjZXB0Og0KICAgICAgICAgICAgcHJp
bnQgc3lzLmV4Y192YWx1ZQ0KICAgICAgICBwcmludA0K
--8323328-26770121-982898217=:4871--