Python中使用語(yǔ)句導(dǎo)入模塊或包的機(jī)制研究
這篇文章討論了Python的from <module> import *和from <package> import *,它們?cè)趺磮?zhí)行以及為什么使用這種語(yǔ)法(也許)是一個(gè)壞主意。
從一個(gè)模塊導(dǎo)入全部
from <module> import * means意味著“我希望能訪問(wèn)<module>中我有權(quán)限訪問(wèn)的全部名稱”。例如以下代碼something.py:
# something.py public_variable = 42 _private_variable = 141 def public_function(): print("I'm a public function! yay!") def _private_function(): print("Ain't nobody accessing me from another module...usually") class PublicClass(object): pass class _WeirdClass(object): pass
在Python解釋器中,我們可以執(zhí)行from something import *,然后看到如下的內(nèi)容:
>>> from something import * >>> public_variable 42 >>> _private_variable ... NameError: name '_private_variable' is not defined >>> public_function() "I'm a public function! yay!" >>> _private_function() ... NameError: name '_private_function' is not defined >>> c = PublicClass() >>> c <something.PublicClass object at ...> >>> c = _WeirdClass() ... NameError: name '_WeirdClass' is not defined
from something import *從something中導(dǎo)入了除了以_開頭名稱外的其他所有名稱,按照規(guī)范,_開始的名稱是私有的所以未被導(dǎo)入。
嗯,不是特別糟!還有什么?
上面沒提到__all__是什么。__all__是一個(gè)字符串列表,指定了當(dāng)from <module> import *被使用時(shí),模塊(或者如后文會(huì)提到的包)中的哪些符號(hào)會(huì)被導(dǎo)出。如果我們不定義__all__(我們?cè)谏厦娴膕omething.py就沒定義),import *默認(rèn)的導(dǎo)入方式是導(dǎo)入除了下劃線(_)開頭的所有名稱。再說(shuō)一次,編程慣例上下劃線表示一個(gè)符號(hào)是私有的,不導(dǎo)入是合理的。讓我們來(lái)看看在something.py中定義我們自己的__all__會(huì)發(fā)生什么。
# something.py __all__ = ['_private_variable', 'PublicClass'] # The rest is the same as before public_variable = 42 _private_variable = 141 def public_function(): print("I'm a public function! yay!") def _private_function(): print("Ain't nobody accessing me from another module...usually") class PublicClass(object): pass class _WeirdClass(object): pass
現(xiàn)在,我們期望from something import *只會(huì)導(dǎo)入_private_variable和PublicClass:
>>> from something import * >>> public_variable 42 >>> _private_variable ... NameError: name '_private_variable' is not defined >>> public_function() "I'm a public function! yay!" >>> _private_function() ... NameError: name '_private_function' is not defined >>> c = PublicClass() >>> c <something.PublicClass object at ...> >>> c = _WeirdClass() ... NameError: name '_WeirdClass' is not defined
包是怎樣的呢?
當(dāng)從一個(gè)包中導(dǎo)入全部時(shí),__all__的做法和模塊基本一樣,不過(guò)它處理的是包中的模塊(而不是把模塊中的名都導(dǎo)入)。所以當(dāng)我們使用from <package> import *.時(shí)__all__說(shuō)明了所有需要被導(dǎo)入當(dāng)前命名空間的模塊。
不同之處在于,如果你在一個(gè)包的__init__.py里面沒有聲明__all__,from <package> import *語(yǔ)句不會(huì)導(dǎo)入任何東西(這個(gè)說(shuō)法也不全對(duì),正確的說(shuō)法在此)
但是,這有什么不好?
繼續(xù)讀之前,在你的Python解釋器中,執(zhí)行import this,再讀一遍Python之禪(在你孩子每晚睡前也要讀給他們)。
明確比含糊要好。
from <module> import * 是不明確的。它沒告訴我們我們正在導(dǎo)入什么或者我們把什么帶入當(dāng)前命名空間了。更好的做法是顯式地導(dǎo)入我們需要的全部名稱。這種方式下,讀者(非常可能是未來(lái)的你自己)就不會(huì)困惑于你代碼中使用的一個(gè)變量/方法/類/其他東西是哪兒來(lái)的,這也告訴了我們下一點(diǎn):
可讀性很重要
即使你需要導(dǎo)入很多東西,一個(gè)一個(gè)顯式地導(dǎo)入也更清楚。使用PEP 328:
from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text, LEFT, DISABLED, NORMAL, RIDGE, END)
你現(xiàn)在就能明確知道你的命名空間里有什么,使用ctrl+f能很快地告訴你它們是哪兒來(lái)的。
同時(shí),你還總是要承擔(dān)模塊/包作者更改list內(nèi)容(加/減東西)的風(fēng)險(xiǎn)。也就是下面兩者之一:
作者從__all__里刪除了一個(gè)字符串。如果你的代碼使用了那個(gè)名字,你的代碼就會(huì)報(bào)出NameError的錯(cuò)誤,并且很難發(fā)現(xiàn)為什么。
作者在__all__里加入了很多東西。你也許不需要這些增加的內(nèi)容,所以你只是讓這些你不關(guān)心的東西占滿了你的命名空間。他們甚至在你不注意的時(shí)候會(huì)替代其他同名內(nèi)容。
當(dāng)然,有時(shí)候從模塊或者包中導(dǎo)入全部?jī)?nèi)容是有用的。不過(guò),這么做之前三思。從我的經(jīng)驗(yàn)來(lái)看,這么做通常只是因?yàn)閼小?br />
- Python 中的 import 機(jī)制之實(shí)現(xiàn)遠(yuǎn)程導(dǎo)入模塊
- 關(guān)于python導(dǎo)入模塊import與常見的模塊詳解
- Python使用import導(dǎo)入本地腳本及導(dǎo)入模塊的技巧總結(jié)
- Python實(shí)現(xiàn)的在特定目錄下導(dǎo)入模塊功能分析
- python導(dǎo)入模塊交叉引用的方法
- 淺談python 導(dǎo)入模塊和解決文件句柄找不到問(wèn)題
- Python動(dòng)態(tài)導(dǎo)入模塊的方法實(shí)例分析
- Python在不同目錄下導(dǎo)入模塊的實(shí)現(xiàn)方法
- Python導(dǎo)入模塊時(shí)遇到的錯(cuò)誤分析
- Python中幾種導(dǎo)入模塊的方式總結(jié)
- Python 專題六 局部變量、全局變量global、導(dǎo)入模塊變量
- python根據(jù)路徑導(dǎo)入模塊的方法
- Python動(dòng)態(tài)導(dǎo)入模塊和反射機(jī)制詳解
相關(guān)文章
python中sleep函數(shù)用法實(shí)例分析
這篇文章主要介紹了python中sleep函數(shù)用法,實(shí)例分析了sleep函數(shù)的功能及使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04pyinstaller執(zhí)行報(bào)錯(cuò)的問(wèn)題解決
有時(shí)候,PyInstaller可能無(wú)法正確識(shí)別和打包所有的依賴項(xiàng),導(dǎo)致名稱錯(cuò)誤,本文主要介紹了pyinstaller執(zhí)行報(bào)錯(cuò)的解決方案,感興趣的可以了解一下2023-11-11在python中利用opencv簡(jiǎn)單做圖片比對(duì)的方法
今天小編就為大家分享一篇在python中利用opencv簡(jiǎn)單做圖片比對(duì)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01Pycharm簡(jiǎn)單使用教程(入門小結(jié))
這篇文章主要介紹了Pycharm簡(jiǎn)單使用教程(入門小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-07-07django 刪除數(shù)據(jù)庫(kù)表后重新同步的方法
今天小編就為大家分享一篇django 刪除數(shù)據(jù)庫(kù)表后重新同步的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05如何用Python中Tushare包輕松完成股票篩選(詳細(xì)流程操作)
這篇文章主要介紹了如何用Python中Tushare包輕松完成股票篩選(詳細(xì)流程操作),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03