本文中所有代碼均運行在Python 2.7上
我們知道,在Python
中的常見包(module)導入有兩種方法:import ...和from ... import ...鼓寺,那么在實際使用過程中酷含,這兩種方法又有哪些不同呢携添?
先說結(jié)論:
- 盡量使用import ...
- 有節(jié)制的使用from ... import ...
- 盡量避免from ... import *
說到原因全蝶,就先來看看import
導入的內(nèi)部機制涯曲。當一個python
文件初始化運行環(huán)境的時候雀监,會加載進來一些python
的內(nèi)建包双吆。這些包在sys.modules
中,使用下面的方法可以獲取這些包的相關信息会前。
>>> import sys
>>> sys.modules.items()
...(我就不告訴你輸出結(jié)果好乐,想要知道請自己實踐)
而所謂的"加載"的過程則分為以下幾步:
- 去
sys.modules
中尋找目標模塊,如果找到瓦宜,就把它導入到當前環(huán)境的局部命名空間蔚万,整個加載過程結(jié)束(一般適用于python的內(nèi)建(built in)模塊);而沒有找到的話就依次執(zhí)行以下操作临庇; - 為目標模塊創(chuàng)建一個特定的
dict
反璃,并插到sys.modules
中; - 對目標模塊進行編譯假夺,這也就是我們?yōu)槭裁纯偰芸匆姾枚?
.pyc
文件的原因淮蜈; - 將編譯結(jié)果放到事先在
sys.modules
中創(chuàng)建的對應dict
中;
那import a和from a import B又有什么區(qū)別呢已卷?
區(qū)別在于前者是將a加入當前的局部命名空間梧田,而后者則將B直接暴露到局部命名空間當中。
那么悼尾,這又會引發(fā)什么問題呢柿扣?
- 命名沖突
假設有模塊a.py:
def echo():
print 'I am echo from module a'
有模塊b.py:
def echo():
print 'I am echo from module b'
我們現(xiàn)在要使用這兩個模塊:
>>> from a import echo
>>> from b import echo
>>> echo()
I am echo from module b
可見,當發(fā)生命名沖突的時候闺魏,后引入的方法或者屬性將覆蓋先引入的未状。
所以,之前說要“有節(jié)制”的使用from a import b
析桥,因為它有命名沖突的隱患司草,只有當明確沒有命名沖突艰垂,并且以下情況下,才使用from ... import ...
- 只使用導入模塊中少數(shù)幾個方法或?qū)傩?/li>
- 這些屬性使用頻繁或者嵌套層級較深埋虹,不便于去使用'a.B'的方式去調(diào)用
- 循環(huán)引用
當處理比較大的項目的時候猜憎,很容易出現(xiàn)下面情況:
有文件py1.py
from py2 import helper2
def helper1():
pass
另有文件py2.py
from py1 import helper1
def helper2():
pass
此時,運行py1.py和py2.py中的任意一個都會報ImportError
搔课。因為py1的運行環(huán)境初始化需要調(diào)用py2的編譯后的字節(jié)碼胰柑,py2亦然。這也是比較常見的錯誤爬泥,需要在實際中注意避免柬讨。