在学习Python时,不少人会问到__builtin__、__builtins__和builtins之间有什么关系。百度或Google一下,有很 多答案,可是这些答案要么不许确,要么只说了一点点,并不全面。本文将给你们一个较为全面的答案。如下结果是通过本人试验过的(测试环境:Linux Mint 14, Python2.7.3和Python3.2.3),并参考了Python的邮件列表。程序员
在Python中,有一个内建模块,该模块中有一些经常使用函数;而该模块在Python启动后、且没有执行程序员所写的任何代码前,Python会首先加载 该内建函数到内存。另外,该内建模块中的功能能够直接使用,不用在其前添加内建模块前缀,其缘由是对函数、变量、类等标识符的查找是按LE(N)GB法 则,其中B即表明内建模块。好比:内建模块中有一个abs()函数,其功能是计算一个数的绝对值,如abs(-20)将返回20。函数
在Python2.X版本中,内建模块被命名为__builtin__,而到了Python3.X版本中,却改名为builtins。学习
当使用内建模块中函数或其它功能时,能够直接使用,不用添加内建模块的名字;可是,若是想要向内建模块中添加一些功能,以便在任何函数中都能直接使用而不 用再进行import,这时,就要导入内建模块,在内建模块的命名空间(即__dict__字典属性)中添加该功能。在导入时,若是是Python2.X 版本,就要导入__builtin__模块;若是是Python3.X版本,就要导入builtins模块。如:在Python2.X中,向内建模块添加 一个函数(该函数打印“hello, world”),能够这样写(如下的用法是在主模块中的使用,其它模块请看下面):测试
import __builtin__ui
def print_hello():spa
print "hello, world"内存
__builtin__.__dict__['hello'] = print_hello作用域
print_hello() # 将打印"hello, world"get
hello() # 将打印"hello, world"it
此时,print_hello和hello两个函数名几乎是同样,可是有一点区别,print_hello只能在该模块中使用,而hello能够在本程序中的其它任何一个模块中使用,由于hello已经放到内建模块中了。
如今,__builtin__和builtins之间的关系已经说清楚了,如今该说说__builtins__了。为了统一Python2.X和Python3.X,在下面的论述中,内建模块一概统称为__builtin__。
由上面的论述,咱们知道,__builtin__存在于Python2.X中,而builtins存在于Python3.X中,可是对于 __builtins__,它却同时存在于Python2.X和Python3.X中。那么它究竟是什么东西呢?由名字可知,它确定与内建模块有关。其实 简单地说,它就是对内建模块一个引用。
一、__builtins__便是引用,那么它内建模块有一个相同点:Python程序一旦启动,它们两者就会在程序员所写的代码没有运行以前就已经被加载到内存中了。
二、虽是一个引用,但__builtins__和内建模块是有一点区别的:
(1)不管任何地方要想使用内建模块,都必须在该位置所处的做用域中导入__builtin__内建模块;而对于__builtins__却不用导入,它在任何模块都直接可见, 能够把它看成内建模块直接使用(这句并不彻底正确,请看第(2)点)。即:__builtins__在任何地方、任何模块均可见,而内建模块名只在相应的 做用域中被import后才能够(该import并非把内建模块加载到内存中——内建早已经被加载了,它仅仅是让内建模块名在该做用域中可见)。
(2)__builtins__虽是对内建模块的引用,但这个引用要看是使用__builtins__的模块是哪一个模块:
1】 在主模块__main__中:
__builtins__是对内建模块__builtin__自己的引用,即__builtins__彻底等价于__builtin__,两者彻底是一个东西,不分彼此。它在任何地方均可见,即在任何地方均可使用它。此时,__builtins__的类型是模块类型。
__builtin__仅仅在导入它时才可见。哪一个做用域中使用__builtin__,哪一个做用域就要导入它(导入仅仅是让__builitin__标 识符在该做用域内可见)。通常都是在模块的顶层(即模块的全局做用域)导入__builtin__,这样,其后的任何做用域可经过标识符向上查找来引用 __builtin__。
2】在非__main__模块中:
__builtins__仅是对__builtin__.__dict__的引用,而非__builtin__自己。它在任何地方均可见。此时__builtins__的类型是字典。
__builtin__和在主模块中的状况同样。
由上面的异同,咱们能够出,__builtins__、__builtin__和builtins之间并无太大的不一样;在使用__builtins__时,只要注意其引用的究竟是__builtin__仍是__builtin__.__dict__便可。
此时,可能会有人说,既然__builtin__和builtins因为Python版本的不一样而不一样,致使在写兼容2.X和3.X版本时的代码时比较麻 烦,而__builtins__在2.X和3.X中都是同样的,那么,再也不使用builtins和__builin__,改用__builtins__不 是更好?!这种作法并无错,可是有一点,在使用__builtins__时,要区分是在主模块__main__中,仍是在其余的非__main__模块 中。笔者看了Python标准库(好比gettext),其中使用的是__builtin__(在Python2.X中)和builtins(在 Python3.X中),而并无使用__builtins__。这仅仅给一些参考。
说明:
主模块__main__:在Python中,一个代码文件就是一个模块,一个模块就是一个代码文件;用来启动Python或者说首先执行的那个文件(至关 于C语言中main主函数所在的C文件)的模块名被Python命名为__main__,称为主模块,而对于其它被主模块或其余非主模块导入的模块,它们 的模块名则是文件名自己(除了后缀.py、.pyc或.pyo等)。每一个模块都有一个名为__name__的属性,它表示着该模块的名字。除此以外,主模 块与其它非主模块之间还有一点区别,好比:from __future__ import absolute_import语句在非主模块中能够正常使用,反而在主模块中,好像没有什么效果——有等无。