预计阅读本页时间:-
The Built-in Scope
We’ve been talking about the built-in scope in the abstract, but it’s a bit simpler than you may think. Really, the built-in scope is just a built-in module called builtins, but you have to import builtins to query built-ins because the name builtins is not itself built-in....
No, I’m serious! The built-in scope is implemented as a standard library module named builtins, but that name itself is not placed in the built-in scope, so you have to import it in order to inspect it. Once you do, you can run a dir call to see which names are predefined. In Python 3.0:
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
>>> import builtins
>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis',
...many more names omitted...
'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set',
'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple',
'type', 'vars', 'zip']
The names in this list constitute the built-in scope in Python; roughly the first half are built-in exceptions, and the second half are built-in functions. Also in this list are the special names None, True, and False, though they are treated as reserved words. Because Python automatically searches this module last in its LEGB lookup, you get all the names in this list “for free;” that is, you can use them without importing any modules. Thus, there are really two ways to refer to a built-in function—by taking advantage of the LEGB rule, or by manually importing the builtins module:
>>> zip # The normal way
<class 'zip'>
>>> import builtins # The hard way
>>> builtins.zip
<class 'zip'>
The second of these approaches is sometimes useful in advanced work. The careful reader might also notice that because the LEGB lookup procedure takes the first occurrence of a name that it finds, names in the local scope may override variables of the same name in both the global and built-in scopes, and global names may override built-ins. A function can, for instance, create a local variable called open by assigning to it:
def hider():
open = 'spam' # Local variable, hides built-in
...
open('data.txt') # This won't open a file now in this scope!
However, this will hide the built-in function called open that lives in the built-in (outer) scope. It’s also usually a bug, and a nasty one at that, because Python will not issue a warning message about it (there are times in advanced programming where you may really want to replace a built-in name by redefining it in your code). Functions can similarly hide global variables of the same name with locals:
X = 88 # Global X
def func():
X = 99 # Local X: hides global
func()
print(X) # Prints 88: unchanged
Here, the assignment within the function creates a local X that is a completely different variable from the global X in the module outside the function. Because of this, there is no way to change a name outside a function without adding a global (or nonlocal) declaration to the def, as described in the next section.[37]
Note
Version skew note: Actually, the tongue twisting gets a bit worse. The Python 3.0 builtins module used here is named __builtin__ in Python 2.6. And just for fun, the name __builtins__ (with the “s”) is preset in most global scopes, including the interactive session, to reference the module known as builtins (a.k.a. __builtin__ in 2.6).
That is, after importing builtins, __builtins__ is builtins is True in 3.0, and __builtins__ is __builtin__ is True in 2.6. The net effect is that we can inspect the built-in scope by simply running dir(__builtins__) with no import in both 3.0 and 2.6, but we are advised to use builtins for real work in 3.0. Who said documenting this stuff was easy?
Breaking the Universe in Python 2.6
Here’s another thing you can do in Python that you probably shouldn’t—because the names True and False in 2.6 are just variables in the built-in scope and are not reserved, it’s possible to reassign them with a statement like True = False. Don’t worry, you won’t actually break the logical consistency of the universe in so doing! This statement merely redefines the word True for the single scope in which it appears. All other scopes still find the originals in the built-in scope.
For more fun, though, in Python 2.6 you could say __builtin__.True = False, to reset True to False for the entire Python process. Alas, this type of assignment has been disallowed in Python 3.0, because True and False are treated as actual reserved words, just like None. In 2.6, though, it sends IDLE into a strange panic state that resets the user code process.
This technique can be useful, however, both to illustrate the underlying namespace model and for tool writers who must change built-ins such as open to customized functions. Also, note that third-party tools such as PyChecker will warn about common programming mistakes, including accidental assignment to built-in names (this is known as “shadowing” a built-in in PyChecker).
[36] The scope lookup rule was called the “LGB rule” in the first edition of this book. The enclosing def “E” layer was added later in Python to obviate the task of passing in enclosing scope names explicitly with default arguments—a topic usually of marginal interest to Python beginners that we’ll defer until later in this chapter. Since this scope is addressed by the nonlocal statement in Python 3.0, I suppose the lookup rule might now be better named “LNGB,” but backward compatibility matters in books, too!
[37] There is technically one more scope in Python: loop variables in comprehension and generator expressions are local to the expression itself in 3.X (in 2.X, they are local in generators but not in list comprehensions). This is a special and obscure case that rarely impacts real code, and differs from for-loop statements which never localize their variables.