[轉]Python-__builtin__與__builtins__的區別與關系(超詳細,經典)


在學習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__

def print_hello():

print "hello, world"

__builtin__.__dict__['hello'] = print_hello

print_hello() # 將打印"hello, world"

hello() # 將打印"hello, world"

此時,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中。那么它到底是什么東西呢?由名字可知,它肯定與內建模塊有關。其實 簡單地說,它就是對內建模塊一個引用。

1、__builtins__即是引用,那么它內建模塊有一個相同點:Python程序一旦啟動,它們二者就會在程序員所寫的代碼沒有運行之前就已經被加載到內存中了。

2、雖是一個引用,但__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語句在非主模塊中可以正常使用,反而在主模塊中,好像沒有什么效果——有等無。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM