[Python-Dev] peps 329, 266, 267

Jewett, Jim J jim.jewett at eds.com
Wed Apr 21 15:02:23 EDT 2004


>> 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.)

> This actually isn't that different from my proposal
> for builtins, 

I had been assuming that class (and instance) attribute
resolution would be subject to the same speedup.

If this is really only about globals and builtins,
then you can just initialize each module's dictionary
with a copy of builtins.  (Or cache them in the module
__dict__ on the first lookup, since you know where it
would have gone.)  This still won't catch updates to 
builtins, but it will eliminate the failed lookup and 
the second dictionary lookup.  

If you really want to track changes to builtin, it is
still faster to echo builtin changes across each module
than it would be to track every name's referrers in
every module (as in PEP 266.)

> 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.

Some of the bugs that got the global tracking backed
out involved changing __builtins__.  If you only add 
to it, then I suppose the current method (which allows 
shadowing) is a reasonable fallback.  It doesn't work 
so well if you want to remove names from builtin.  

In fairness, the language spec does warn that a new 
builtin dict may contain more than you expect, and I
suppose it could be created with extra names pointed
to NotImplemented instead of just raising a NameError.

>>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.  

It could be converted to LOAD_CELL (or perhaps even
LOAD_FAST) if the compiler were allowed to assume no 
changes in shadowing.  (Including an assumption that 
the same dictionaries will continue to represent the 
globals and builtin namespaces for this code object.)

> 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.)

Why not just make NameDict a subclass that has a different
__setitem__?  The times when eval cares should be exactly 
the times when you need to do extra checks.  This also lets 
you use something like DLict (PEP 267) to move most lookup
overhead to compile-time.

-jJ



More information about the Python-Dev mailing list