[Python-Dev] peps 329, 266, 267
Phillip J. Eby
pje at telecommunity.com
Wed Apr 21 13:48:33 EDT 2004
At 12:28 PM 4/21/04 -0400, Jewett, Jim J wrote:
> from __future__ import noshadow
> If a name (or its immediately enclosing class)
> is explicitly declared dynamic, semantics are
> the same as today.
How do you declare that something is dynamic?
> For all other names, the compiler may assume that
> the nearest enclosing binding of this name will
> always be in the same namespace. (Names need not
> all be in a single namespace, but once a particular
> name is found, that namespace will always be the
> correct place to look for that name.)
> Results are undefined if the name is later unbound
> in that namespace or shadowed by a nearer enclosing
This actually isn't that different from my proposal for builtins, except
that my proposal doesn't have "undefined results". Instead, names that are
determined to be builtin are not allowed to be bound via __setattr__, and
are never looked up in the globals dictionary.
>Question: Should the compiler be able to assume the
>same *object* (=can bind as local), or only the same
>namespace (=can do with a single indirection, perhaps
>sped up with a variant of DLict).
>Question: Is there any reason that this should apply
>only to builtins, rather than to any namespace?
Simplicity. Functions today do only three kinds of lookups: LOAD_CELL(?),
LOAD_FAST and LOAD_GLOBAL. LOAD_CELL is an indirect load from a known,
specific nested scope. LOAD_FAST loads from an array offset into the
current frame object. LOAD_GLOBAL checks globals and then
builtins. Module-level and class body code use LOAD_NAME, which looks in
locals, globals, and builtins.
Module and class body code is almost never important for application
performance, certainly not enough to justify effort on optimization, I think.
So that leaves LOAD_GLOBAL, which I suggest leaving alone in favor of
adding LOAD_BUILTIN and/or CALL_BUILTIN. In other words, at that point all
lookups made by functions *would* be explicit as to scope, since
LOAD_GLOBAL could only fail its first lookup if the global in question was
a not-yet-shadowed-but-expected-to-be builtin.
>Objection: Users can do something undefined and get
>"normal" results instead of a warning -- on their own
>platform. They can even do this strictly through
>changes to other modules which do not themselves
>import noshadow. How serious is this objection?
I think my proposal adequate deals with this by disallowing shadowing at
runtime. And, if it was desired to disallow shadowing by modifiying
globals(), then perhaps globals() and module.__dict__ could simply return a
dictionary proxy that prevented modification of the disallowed
values. (But the bare dictionary would still be used by the eval loop.)
>If a warning is required, will the bookkeeping be
>needed even in release mode, or will it be an option
>depending on compiler settings?
The runtime checking in my proposal only requires a bit of work at module
setup, and checking when a module attribute is set. Neither of these occur
frequently enough in general to be concerned about.
More information about the Python-Dev