Python 中的模块和包
原文引至:前端小吉米
對于python中的模塊和包, 我簡直就想說, js nmlgb 就是一個 trash... 在前端寫js根本就沒有什么模塊和包, 全部都是全局... 真lj...
暢快了. 寫了這么久的js, 連內部的模塊的包都搞的這么復雜... 艸...
在python中, 已經定義好了完美的模塊和包的引用機制.
我們先來看看Module
Module
在python中, 模塊實際上,就相當于與業務邏輯解耦的可重用的一些函數方法. 所以, 我們可以預先定義一個模塊:
// 命令為sam.py def add(a,b):return a+b之后在同目錄中,打開一個 Terminator.
接著輸入:
實際上, 這就是一個簡單的模塊. 但,當我們導入的時候, 會在Module的目錄中生成一個.pyc文件, 該其實就是用來對Module進行緩存,并編譯為Binary 文件, 以便py以后再次引入.
現在, 我們已經學會如何寫入Module,引入Module. 這里,我們需要更進一步去探索, python是如何進行Module Path的搜索的.
模塊路徑搜索
在nodeJS中, 他的搜索方式是, 先看內部定義的Module 有沒有. 沒有的話,則會開始尋找每一層的node_modules. 然后在里面搜索你的文件.js
那么在py中,他是怎樣一個過程呢?
py將搜索路徑,放在了sys.path中.我們可以查看一下. sys.path里面的內容.
然后就會出現, 一些路徑,比如這個:
['', 'C:\\Python33\\Lib\\lib-dynload', 'C:\\Windows\\system32\\python33.zip', 'C:\\Python33\\DLLs', 'C:\\Python33\\lib', 'C:\\Python33\\plat-darwin', 'C:\\Python33\\lib\\site-packages']可以看到, 第一個為空, 他實際代表的就是current directory.
具體的順序是:
當前目錄
sys.path定義的相關目錄
安裝依賴的目錄
所以, 如果你想自定義自己的Module 直接添加在sys.path里面即可.
那應該怎樣進行添加呢?
實際上, 這就是查找關于sys.path的方法了. 還記得help()嗎?
查找后,我們基本上都會明白了. md, 這不就是list嗎?
那剩下的不就是調用,list的方法進行添加和刪除嗎?
一般而言,python的工作目錄是放在對應的pythonLib文件夾內.這里,我將我常用的py 模塊路徑添加進去
之后, 我只要將我寫好的Module 放在指定的文件內即可.
模塊進階
上面, 我們只是學會使用基本的Module 導入, 實際上,py提供了 更加豐富的Module statement.
比如, 重命名, 指定導入, 全導入
Module rename
這個算是一個py Module的一個附加值吧.
具體用法很簡單.
就醬, 實際上,就是使用as將模塊的名字換一個. 并且, 換了之后sam, 也就不存在了.
Specific Module
直接看demo吧:
//直接導入 add方法 from sam import add // 也可以導入多個 from sam import add,minus這樣導入的結果也是, 不能使用sam.
如果你想, 將module里面所有的方法都導入的話, 直接使用* 即可
不過, 真強烈不建議這么做. 因為, 并沒有什么卵用, 并且, 萬一出現什么bug, 都不知道這個方法哪來的.
Module complement
在nodeJS中, 他的模塊引用是值引用類型, 即就是, 一次引用之后, 就會放在緩存里面, 以后如果在引用的話, 會直接從緩存里面取了.
看一個demo:
只會出現一次, 說明, sam Module 只能導入一次. 其余的就 nonesense. 但是,如果你的模塊是內部循環型的, 那這樣不就go die了嗎?
hehe ~ py 早教看到這一點了, 在內置的imp中提供了reload方法, 來幫助我們實現, 模塊的引用更新
最后在補充一個dir(module)方法. 他的作用,就是用來查看指定Module當中的全局變量和函數名.
>>> dir(sam) ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'add']其余的用underscore來連接的, 是py中 module的一部分. 比較重要的看一下__name__即可. 他是用來表示,你當前所在的程序是模塊,還是主程序.
如果你是主程序則 __name__ 為 main
如果為模塊則 __name__ 為 你的模塊名
另外,如果你忽略參數, 直接使用dir()的話,就是用來查看當前 全局中的變量和函數名.
>>> dir() ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', '__warningregistry__', 'get', 'imp', 'sam', 'set']但,如果你導入一個內置模塊的話, 比如: copy
>>> import copy >>> dir(copy) ['Error', 'PyStringMap', '_EmptyClass', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', ...]仔細觀察, 里面的內置屬性, 會看到多出一個叫__all__的屬性. 這其實和下面所說的包有一些關系. 實際上, __all__ 的作用, 是提供公共接口的, 但實際上, 當我們導入方法的時候, 往往會全部倒入.比如這樣.
import copy那么此時, __all__ 對于這種方法是沒有任何作用, 該語句就是用來導入copy下所有的全局變量.
現在, 假設 當前模塊sam.py下有2個方法,add,minus.
我將__all__ 設置為
我們來試驗一下兩者的區別:
//首先導入: >>> import sam >>> dir() ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'sam'] >>> dir(sam) ['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'add', 'minus']可以看到,有了sam這個模塊名. 并且, 查看sam中,會看到有add和minus方法.
然后,我們換一種方式導入:
我們會發現, minus不見了.
所以, 這里我們就可以搞懂了__all__ 到底是用來做什么的.
__all__: 用來設置模塊的公共接口. 并且只針對于 from module import * 的語句
最后在說一下,其中的另外兩個默認屬性 __doc__,__file__
__doc__: 實際上,就是我們使用help()函數查看的內容. 內容具體就是我們寫在模塊開頭或者函數開頭的注釋
__file__: 模塊真實的文件路徑, 如果你想查看源碼的時候就很重要了.
放圖:
Package
說完了,py中的Module, 接著就是最讓你66的包. Module只是幫助我們完成了一個組件的一些小功能, 但是如果我們想要寫一個可以調用的整體組件的話, 那么一個single Module顯然是不夠了. 所以,py 推出了package 來幫助我們完成這個巨大的工程(project). 我們可以通過個文件,調用,該組件下所有的方法. 比如,我們需要寫一個html的評論框, 那么里面肯定會設計, HTML,css,js樣式設計, 接收評論,發布評論等很多功能. 在包里面, 我們就可以把這些小功能進行拆分,達到復用的效果.
先看張圖:
這實際上, 就是我們python包的簡單格式, 在每個文件根目錄都會存在__init.py__ 文件. 他的作用實際上,就是用來定義, 引用包時, 暴露的相關接口. 而關鍵的關鍵, 就是上面提到的__all__ 內置的默認關鍵字. how to use?
請, stackoverflow.
__init__.py就是一個導入文件
現在,我們來寫一個簡單的包, 以上圖為例。
在Game的根目錄下, __init__.py內容為:
然后,我們就可以直接應用Game 包了.
>>>import Game >>>Game.Sound.xxx這里,需要說明的是, 關于包的導入, 其實用不用all不是很重要, 換句話說, 應該是不推薦, 因為前文我們已經了解到, __all__ 生效的機制是 使用 from xx import * 這樣的語句. 而這樣做的實際效果是, 完全破壞了python的namespace機制, 也是編程語言中最重要的一個. 所以, 給的建議就是, 盡量放棄all的使用, 直接使用 import 來判斷你需要導出那些公共的接口即可.
引用一段話:
Leaving an __init__.py file empty is considered normal and even a good practice, if the package’s modules and sub-packages do not need to share any code.
出自: python guider
總結
以上是生活随笔為你收集整理的Python 中的模块和包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux系统结构与文件管理命令
- 下一篇: websocket python爬虫_p