国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python中使用語句導(dǎo)入模塊或包的機(jī)制研究

2019-11-25 17:53:50
字體:
供稿:網(wǎng)友

這篇文章討論了Python的from <module> import *和from <package> import *,它們怎么執(zhí)行以及為什么使用這種語法(也許)是一個(gè)壞主意。
從一個(gè)模塊導(dǎo)入全部

from <module> import * means意味著“我希望能訪問<module>中我有權(quá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_variable42>>> _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í),模塊(或者如后文會提到的包)中的哪些符號會被導(dǎo)出。如果我們不定義__all__(我們在上面的something.py就沒定義),import *默認(rèn)的導(dǎo)入方式是導(dǎo)入除了下劃線(_)開頭的所有名稱。再說一次,編程慣例上下劃線表示一個(gè)符號是私有的,不導(dǎo)入是合理的。讓我們來看看在something.py中定義我們自己的__all__會發(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 *只會導(dǎo)入_private_variable和PublicClass:
 

>>> from something import *>>> public_variable42>>> _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__的做法和模塊基本一樣,不過它處理的是包中的模塊(而不是把模塊中的名都導(dǎo)入)。所以當(dāng)我們使用from <package> import *.時(shí)__all__說明了所有需要被導(dǎo)入當(dāng)前命名空間的模塊。

不同之處在于,如果你在一個(gè)包的__init__.py里面沒有聲明__all__,from <package> import *語句不會導(dǎo)入任何東西(這個(gè)說法也不全對,正確的說法在此
但是,這有什么不好?

繼續(xù)讀之前,在你的Python解釋器中,執(zhí)行import this,再讀一遍Python之禪(在你孩子每晚睡前也要讀給他們)。

    明確比含糊要好。

from <module> import * 是不明確的。它沒告訴我們我們正在導(dǎo)入什么或者我們把什么帶入當(dāng)前命名空間了。更好的做法是顯式地導(dǎo)入我們需要的全部名稱。這種方式下,讀者(非常可能是未來的你自己)就不會困惑于你代碼中使用的一個(gè)變量/方法/類/其他東西是哪兒來的,這也告訴了我們下一點(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能很快地告訴你它們是哪兒來的。

同時(shí),你還總是要承擔(dān)模塊/包作者更改list內(nèi)容(加/減東西)的風(fēng)險(xiǎn)。也就是下面兩者之一:

    作者從__all__里刪除了一個(gè)字符串。如果你的代碼使用了那個(gè)名字,你的代碼就會報(bào)出NameError的錯(cuò)誤,并且很難發(fā)現(xiàn)為什么。
    作者在__all__里加入了很多東西。你也許不需要這些增加的內(nèi)容,所以你只是讓這些你不關(guān)心的東西占滿了你的命名空間。他們甚至在你不注意的時(shí)候會替代其他同名內(nèi)容。

當(dāng)然,有時(shí)候從模塊或者包中導(dǎo)入全部內(nèi)容是有用的。不過,這么做之前三思。從我的經(jīng)驗(yàn)來看,這么做通常只是因?yàn)閼小?br />

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 方正县| 吴桥县| 鲜城| 射洪县| 惠安县| 渭源县| 久治县| 阳谷县| 内黄县| 孟州市| 楚雄市| 镇原县| 温泉县| 伊通| 印江| 太白县| 晋城| 巴青县| 阳江市| 离岛区| 会同县| 连南| 资溪县| 阿瓦提县| 玛多县| 新郑市| 田阳县| 山西省| 伊宁县| 诏安县| 稷山县| 江津市| 夏邑县| 寿光市| 英德市| 诸暨市| 永清县| 贵定县| 定州市| 桃江县| 陆川县|