0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

用Python編寫模塊有何技巧?

5RJg_mcuworld ? 來源:未知 ? 作者:胡薇 ? 2018-10-16 15:53 ? 次閱讀

隨著對(duì)Python學(xué)習(xí)的深入,其優(yōu)點(diǎn)日漸突出,讓讀者也感覺到Python的強(qiáng)大了,強(qiáng)大感覺之一就是“模塊自信”,因?yàn)镻ython不僅有自帶的模塊(稱之為標(biāo)準(zhǔn)庫(kù)),還有海量的第三方模塊,并且很多開發(fā)者還在不斷貢獻(xiàn)自己開發(fā)的新模塊,正是有了這么強(qiáng)大的“模塊自信”,Python才被很多人鐘愛。并且這種方式也正在不斷被其他更多語言所借鑒,幾乎成為普世行為了(不知道Python是不是首倡者)。

“模塊自信”的本質(zhì)是:開放。

Python不是一個(gè)封閉的體系,而是一個(gè)開放系統(tǒng)。開放系統(tǒng)的最大好處就是避免了“熵增”。

熵的概念是由德國(guó)物理學(xué)家克勞修斯于1865年所提出,是一種測(cè)量在動(dòng)力學(xué)方面不能做功的能量總數(shù),也就是當(dāng)總體的熵增加,其做功能力也下降,熵的量度正是能量退化的指標(biāo)。

熵亦被用于計(jì)算一個(gè)系統(tǒng)中的失序現(xiàn)象,也就是計(jì)算該系統(tǒng)混亂的程度。

根據(jù)熵的統(tǒng)計(jì)學(xué)定義,熱力學(xué)第二定律說明一個(gè)孤立系統(tǒng)傾向于增加混亂程度。換句話說就是對(duì)于封閉系統(tǒng)而言,會(huì)越來越趨向于無序化。反過來,開放系統(tǒng)則能避免無序化。

編寫模塊

想必讀者已經(jīng)熟悉了import語句,曾經(jīng)有這樣一個(gè)例子:

1>>>importmath2>>>math.pow(3,2)9.0

這里的math(是Python標(biāo)準(zhǔn)庫(kù)之一,我們要逐漸理解模塊、庫(kù)之類的術(shù)語。)就是一個(gè)模塊,用import引入這個(gè)模塊,然后可以使用模塊里面的函數(shù),比如pow()函數(shù)。顯然,這里是不需要自己動(dòng)手寫具體函數(shù)的,我們的任務(wù)就是拿過來使用。這就是模塊的好處:拿過來就用,不用自己重寫。

1. 模塊是程序

“模塊是程序”一語道破了模塊的本質(zhì),它就是一個(gè)擴(kuò)展名為.py的Python程序。

我們能夠在應(yīng)該使用它的時(shí)候?qū)⑺眠^來,節(jié)省精力,不需要重寫雷同的代碼。

但是,如果我自己寫一個(gè).py文件,是不是就能作為模塊import過來呢?還不那么簡(jiǎn)單。必須得讓Python解釋器能夠找到你寫的模塊。比如,在某個(gè)目錄中,我寫了這樣一個(gè)文件:

1#!/usr/bin/envpython#coding=utf-8lang="python"

并把它命名為pm.py,那么這個(gè)文件就可以作為一個(gè)模塊被引入。不過由于這個(gè)模塊是我自己寫的,Python解釋器并不知道,得先告訴它我寫了這樣一個(gè)文件。

1>>>importsys2>>>sys.path.append("~/Documents/VBS/StartLearningPython/2code/pm.py")

用這種方式告訴Python解釋器,我寫的那個(gè)文件在哪里。在這個(gè)方法中,也用了模塊import sys,不過由于sys是Python標(biāo)準(zhǔn)庫(kù)之一,所以不用特別告訴Python解釋器其位置。

上面那個(gè)一長(zhǎng)串的地址是Ubuntu系統(tǒng)的地址格式,如果讀者使用的是Windows系統(tǒng),請(qǐng)寫你所保存的文件路徑。

1>>>importpm2>>>pm.lang'python'

在pm.py文件中有一個(gè)賦值語句,即lang = "python",現(xiàn)在將pm.py作為模塊引入(注意作為模塊引入的時(shí)候不帶擴(kuò)展名),就可以通過“模塊名字”+“.”+“屬性或方法名稱”來訪問pm.py中的東西。當(dāng)然,如果要訪問不存在的屬性,肯定是要報(bào)錯(cuò)的。

1>>>pm.xx23Traceback(mostrecentcalllast):45File"",line1,inAttributeError:'module'objecthasnoattribute'xx'

請(qǐng)讀者回到pm.py文件的存儲(chǔ)目錄,查看一下是不是多了一個(gè)擴(kuò)展名是.pyc的文件?

解釋器,英文是:interpreter,在Python中,它的作用就是將.py的文件轉(zhuǎn)化為.pyc文件,而.pyc文件是由字節(jié)碼(bytecode)構(gòu)成的,然后計(jì)算機(jī)執(zhí)行.pyc文件。

很多人喜歡將這個(gè)世界簡(jiǎn)化再簡(jiǎn)化,比如編程語言就分為解釋型和編譯型,不但如此,還將兩種類型的語言分別貼上運(yùn)行效率高低的標(biāo)簽,解釋型的運(yùn)行速度就慢,編譯型的運(yùn)行速度就快。一般人都把Python看成是解釋型的,于是就得出它運(yùn)行速度慢的結(jié)論。不少人都因此上當(dāng)受騙了,認(rèn)為Python不值得學(xué),或者做不了什么“大事”。這就是將本來復(fù)雜的、多樣化的世界非得劃分為“黑白”的結(jié)果,喜歡用“非此即彼”的思維方式考慮問題。

世界是復(fù)雜的,“敵人的敵人就是朋友”是幼稚的,“一分為二”是機(jī)械的。

如同剛才看到的那個(gè).pyc文件一樣,當(dāng)Python解釋器讀取了.py文件,先將它變成由字節(jié)碼組成的.pyc文件,然后這個(gè).pyc文件交給一個(gè)叫作Python虛擬機(jī)的東西去運(yùn)行(那些號(hào)稱編譯型的語言也是這個(gè)流程,不同的是它們先有一個(gè)明顯的編譯過程,編譯好了之后再運(yùn)行)。如果.py文件修改了,Python解釋器會(huì)重新編譯,只是這個(gè)編譯過程不全顯示給你看。

有了.pyc文件后,每次運(yùn)行就不需要重新讓解釋器來編譯.py文件了,除非.py文件修改了。這樣,Python運(yùn)行的就是那個(gè)編譯好了的.pyc文件。

是否還記得前面寫有關(guān)程序然后執(zhí)行時(shí)常常要用到if __name__ == "__main__",那時(shí)我們直接用“python filename.py”的格式來運(yùn)行該文件,此時(shí)我們也同樣有了.py文件,不過是作為模塊引入的。這就得深入探究一下,同樣是.py文件,它怎么知道是被當(dāng)作程序執(zhí)行還是被當(dāng)作模塊引入?

為了便于比較,將pm.py文件進(jìn)行改造。

1#!/usr/bin/envpython#coding=utf-8deflang():23return"python"if__name__=="__main__":45printlang()

沿用先前的做法:

1$pythonpm.py23python

如果將這個(gè)程序作為模塊,導(dǎo)入,會(huì)是這樣的:

1>>>importsys2>>>sys.path.append("~/Documents/VBS/StarterLearningPython/2code/pm.py")>>>importpm3>>>pm.lang()'python'

查看模塊屬性和方法,可以使用dir()。

1>>>dir(pm)['__builtins__','__doc__','__file__','__name__','__package__','lang']

同樣一個(gè).py文件,可以把它當(dāng)作程序來執(zhí)行,也可以將它作為模塊引入。

1>>>__name__'__main__'>>>pm.__name__'pm'

如果要作為程序執(zhí)行,則__name__ == "__main__";如果作為模塊引入,則pm.__name__ == "pm",即變量__name__的值是模塊名稱。

用這種方式就可以區(qū)分是執(zhí)行程序還是作為模塊引入了。

在一般情況下,如果僅僅是用作模塊引入,不必寫if __name__ == "__main__"。

2. 模塊的位置

為了讓我們自己寫的模塊能夠被Python解釋器知道,需要用sys.path.append("~/Documents/ VBS/StarterLearningPython/2code/pm.py")。其實(shí),在Python中,所有模塊都被加入到了sys.path里面。用下面的方法可以看到模塊所在位置:

1>>>importsys 2>>>importpprint 3>>>pprint.pprint(sys.path)['', 4 5'/usr/local/lib/python2.7/dist-packages/autopep8-1.1-py2.7.egg', 6 7'/usr/local/lib/python2.7/dist-packages/pep8-1.5.7-py2.7.egg', 8 9'/usr/lib/python2.7',1011'/usr/lib/python2.7/plat-i386-linux-gnu',1213'/usr/lib/python2.7/lib-tk',1415'/usr/lib/python2.7/lib-old',1617'/usr/lib/python2.7/lib-dynload',1819'/usr/local/lib/python2.7/dist-packages',2021'/usr/lib/python2.7/dist-packages',2223'/usr/lib/python2.7/dist-packages/PILcompat',2425'/usr/lib/python2.7/dist-packages/gtk-2.0',2627'/usr/lib/python2.7/dist-packages/ubuntu-sso-client',2829'~/Documents/VBS/StarterLearningPython/2code/pm.py']

從中也發(fā)現(xiàn)了我自己寫的那個(gè)文件。

凡在上面列表所包括位置內(nèi)的.py文件都可以作為模塊引入。不妨舉個(gè)例子,把前面自己編寫的pm.py文件修改為pmlib.py,然后復(fù)制到'/usr/lib/python2.7/dist-packages中。(這是以Ubuntu為例說明,如果是其他操作系統(tǒng),讀者用類似方法也能找到。)

1$sudocppm.py/usr/lib/python2.7/dist-packages/pmlib.py23[sudo]passwordforqw:456$ls/usr/lib/python2.7/dist-packages/pm*78/usr/lib/python2.7/dist-packages/pmlib.py

文件放到了指定位置。看下面的:

1>>>importpmlib2>>>pmlib.lang>>>pmlib.lang()'python'

將模塊文件放到指定位置是一種不錯(cuò)的方法,但感覺此法受到了拘束,程序員都喜歡自由,能不能放到別處呢?

當(dāng)然能,用sys.path.append()就是不管把文件放在哪里,都可以把其位置告訴Python解釋器。雖然這種方法在前面用了,但其實(shí)是很不常用的,因?yàn)樗灿新闊┑牡胤?,比如在交互模式下,如果關(guān)閉了,再開啟,還得重新告知。

比較常用的方法是設(shè)置PYTHONPATH環(huán)境變量。

環(huán)境變量,不同的操作系統(tǒng)設(shè)置方法略有差異。讀者可以根據(jù)自己的操作系統(tǒng),到網(wǎng)上搜索設(shè)置方法。

以Ubuntu為例,建立一個(gè)Python的目錄,然后將我自己寫的.py文件放到這里,并設(shè)置環(huán)境變量。

1:~$mkdirpython23:~$cdpython45:~/python$cp~/Documents/VBS/StarterLearningPython/2code/pm.pymypm.py67:~/python$ls89mypm.py

然后將這個(gè)目錄~/python,即/home/qw/python設(shè)置環(huán)境變量。

1vim/etc/profile

要用root權(quán)限,在打開的文件最后增加export PATH = /home/qw/python:$PATH,然后保存退出即可。

注意,我是在~/python目錄下輸入Python,然后進(jìn)入到交互模式:

1:~$cdpython:~/python$python>>>importmypm>>>mypm.lang()'python'

如此,就完成了告知過程。

3. __all__在模塊中的作用

上面的模塊雖然比較簡(jiǎn)單,但是已經(jīng)顯示了編寫模塊,以及在程序中導(dǎo)入模塊的基本方式。在實(shí)踐中,所編寫的模塊也許更復(fù)雜一點(diǎn),比如,有這么一個(gè)模塊,其文件命名為pp.py

1#/usr/bin/envpython#coding:utf-8public_variable="Hello,Iamapublicvariable."_private_variable="Hi,Iamaprivatevariable."defpublic_teacher():23print"Iamapublicteacher,IamfromJP."def_private_teacher():45print"Iamaprivateteacher,IamfromCN."

接下來就是熟悉的操作了,進(jìn)入到交互模式中。pp.py這個(gè)文件就是一個(gè)模塊,該模塊中包含了變量和函數(shù)。

1>>>importsys 2>>>sys.path.append("~/Documents/StarterLearningPython/2code/pp.py") 3>>>importpp 4>>>fromppimport* 5>>>public_variable'Hello,Iamapublicvariable.' 6>>>_private_variable 7 8Traceback(mostrecentcalllast): 910File"",line1,inNameError:name'_private_variable'isnotdefined

變量public_variable能夠被使用,但是另外一個(gè)變量_private_variable不能被調(diào)用,先觀察一下兩者的區(qū)別,后者是以單下畫線開頭的,這樣的是私有變量。而from pp import *的含義是“希望能訪問模塊(pp)中有權(quán)限訪問的全部名稱”,那些被視為私有的變量或者函數(shù)或者類,當(dāng)然就沒有權(quán)限被訪問了。

再如:

1>>>public_teacher()23Iamapublicteacher,IamfromJP.4>>>_private_teacher()Traceback(mostrecentcalllast):56File"",line1,inNameError:name'_private_teacher'isnotdefined

這不是絕對(duì)的,但如果要訪問具有私有性質(zhì)的東西,可以這樣做。

1>>>importpp2>>>pp._private_teacher()Iamaprivateteacher,IamfromCN.3>>>pp._private_variable'Hi,Iamaprivatevariable.'

下面再對(duì)pp.py文件進(jìn)行改寫,增加一些東西。

1#/usr/bin/envpython#coding:utf-8__all__=['_private_variable','public_teacher']public_variable="Hello,Iamapublicvariable."_private_variable="Hi,Iamaprivatevariable."defpublic_teacher():23print"Iamapublicteacher,IamfromJP."def_private_teacher():45print"Iamaprivateteacher,IamfromCN."

在修改之后的pp.py中,增加了__all__變量以及相應(yīng)的值,在列表中包含了一個(gè)私有變量的名字和一個(gè)函數(shù)的名字。這是在告訴引用本模塊的解釋器,這兩個(gè)東西是有權(quán)限被訪問的,而且只有這兩個(gè)東西。

1>>>importsys2>>>sys.path.append("~/Documents/StarterLearningPython/2code/pp.py")3>>>fromppimport*4>>>_private_variable'Hi,Iamaprivatevariable.'

果然,曾經(jīng)不能被訪問的私有變量,現(xiàn)在能夠訪問了。

1>>>public_variable23Traceback(mostrecentcalllast):45File"",line1,inNameError:name'public_variable'isnotdefined

因?yàn)檫@個(gè)變量沒有在__all__的值中,雖然以前曾經(jīng)被訪問到過,但是現(xiàn)在就不行了。

1>>>public_teacher()Iamapublicteacher,IamfromJP.>>>_private_teacher()Traceback(mostrecentcalllast):23File"",line1,inNameError:name'_private_teacher'isnotdefined

這只不過是再次說明前面的結(jié)論罷了。當(dāng)然,如果以import pp引入模塊,再用pp._private_teacher的方式是一樣有效的。

4. 包和庫(kù)

顧名思義,包和庫(kù)都是比“模塊”大的。一般來講,一個(gè)“包”里面會(huì)有多個(gè)模塊,當(dāng)然,“庫(kù)”是一個(gè)更大的概念了,比如Python標(biāo)準(zhǔn)庫(kù)中的每個(gè)庫(kù)都有好多個(gè)包,每個(gè)包都有若干個(gè)模塊。

一個(gè)包由多個(gè)模塊組成,即有多個(gè).py的文件,那么這個(gè)所謂的“包”就是我們熟悉的一個(gè)目錄罷了?,F(xiàn)在需要解決如何引用某個(gè)目錄中的模塊問題。解決方法就是在該目錄中放一個(gè)__init__.py文件。__init__.py是一個(gè)空文件,將它放在某個(gè)目錄中,就可以將該目錄中的其他.py文件作為模塊被引用。

例如,建立一個(gè)目錄,名曰:package_qi,里面依次放了pm.py和pp.py兩個(gè)文件,然后建立一個(gè)空文件__init__.py

接下來,需要導(dǎo)入這個(gè)包(package_qi)中的模塊。

下面這種方法很清晰明了。

1>>>importpackage_qi.pm2>>>package_qi.pm.lang()'python'

下面這種方法,貌似簡(jiǎn)短,但如果多了,恐怕難以分辨。

1>>>frompackage_qiimportpm2>>>pm.lang()'python'

在后續(xù)制作網(wǎng)站的實(shí)戰(zhàn)中,還會(huì)經(jīng)常用到這種方式,屆時(shí)會(huì)了解更多。請(qǐng)保持興趣繼續(xù)閱讀,不要半途而廢,不然疑惑得不到解決,好東西就看不到了。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • python
    +關(guān)注

    關(guān)注

    55

    文章

    4774

    瀏覽量

    84386

原文標(biāo)題:如何用Python編寫模塊?

文章出處:【微信號(hào):mcuworld,微信公眾號(hào):嵌入式資訊精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    學(xué)python哪些方向?

    科學(xué)計(jì)算、繪制高質(zhì)量的2D和3D圖像。9. 游戲開發(fā)在網(wǎng)絡(luò)游戲開發(fā)中,Python也有很多應(yīng)用,相比于Lua or C++,Python比Lua更高階的抽象能力,可以更少的代碼描述
    發(fā)表于 03-09 15:47

    可以Python去取代MATLAB嗎

    SCILAB是什么?Octave是什么?Octave作用?可以Python去取代MATLAB嗎?
    發(fā)表于 11-22 07:01

    OpenCV-Python-Toturial-中文版

    python編寫opencv的入門資料,介紹了python的各個(gè)函數(shù)的應(yīng)用
    發(fā)表于 03-23 14:55 ?0次下載

    分享一份網(wǎng)友學(xué)習(xí)python時(shí)編寫的一個(gè)小工具

    EETOP網(wǎng)友很多是IC設(shè)計(jì)相關(guān)的,特別是從事IC驗(yàn)證的,經(jīng)常會(huì)編寫腳本,以前的最多的應(yīng)該是Perl語言,隨著python的流行,也有很多人開始學(xué)習(xí)Python. 今天分享一份
    的頭像 發(fā)表于 01-22 10:43 ?7289次閱讀
    分享一份網(wǎng)友學(xué)習(xí)<b class='flag-5'>python</b>時(shí)<b class='flag-5'>編寫</b>的一個(gè)小工具

    如何使用Python編寫一個(gè)桌面軟件系統(tǒng)?步驟哪些

    建議直接python編寫一個(gè)網(wǎng)頁服務(wù)器,然后就在本機(jī)瀏覽器來使用。
    的頭像 發(fā)表于 01-25 12:08 ?4825次閱讀

    如何使用Python編寫一個(gè)簡(jiǎn)單的程序

    按照軟件行業(yè)傳統(tǒng)習(xí)慣,當(dāng)你學(xué)習(xí)一種新的編程語言如Python時(shí),首先編寫一個(gè)“Hello World! ”程序。請(qǐng)執(zhí)行以下步驟,以創(chuàng)造你的“Hello World!” Python程序。
    的頭像 發(fā)表于 01-16 15:21 ?2.2w次閱讀

    python包、模塊和庫(kù)是什么

    1. 模塊 以 .py 為后綴的文件,我們稱之為 模塊,英文名 Module。 模塊讓你能夠邏輯地組織你的 Python 代碼段,把相關(guān)的
    的頭像 發(fā)表于 03-09 16:47 ?2289次閱讀

    如何使用Warp在Python環(huán)境中編寫CUDA內(nèi)核

      通常,實(shí)時(shí)物理模擬代碼是低級(jí) CUDA C ++編寫的,以獲得最佳性能。在這篇文章中,我們將介紹 NVIDIA Warp ,這是一個(gè)新的 Python 框架,可以輕松地
    的頭像 發(fā)表于 04-02 16:15 ?2520次閱讀

    淺析python模塊創(chuàng)建和from及import使用

    python模塊通過python程序編寫的.py文件即可創(chuàng)建,通過from及import語句導(dǎo)入模塊
    的頭像 發(fā)表于 02-21 14:44 ?788次閱讀

    利用Python編寫簡(jiǎn)單網(wǎng)絡(luò)爬蟲實(shí)例

    利用 Python編寫簡(jiǎn)單網(wǎng)絡(luò)爬蟲實(shí)例2 實(shí)驗(yàn)環(huán)境python版本:3.3.5(2.7下報(bào)錯(cuò)
    發(fā)表于 02-24 11:05 ?14次下載

    Python中telnetlib模塊的基本使用

    telnetlib 是 Python 標(biāo)準(zhǔn)庫(kù)中的一個(gè)模塊,它提供了 Telnet 協(xié)議的客戶端功能。使用 telnetlib 模塊,我們可以在 Python
    的頭像 發(fā)表于 05-04 14:27 ?7865次閱讀

    python什么 如何用python創(chuàng)建數(shù)據(jù)庫(kù)

    python什么 如何用python創(chuàng)建數(shù)據(jù)庫(kù) Python是一種高級(jí)編程語言,可以用于開發(fā)各種類型的應(yīng)用程序和工具。它的廣泛應(yīng)用使它在
    的頭像 發(fā)表于 08-28 16:41 ?1134次閱讀

    TinyDB :一個(gè)純Python編寫的輕量級(jí)數(shù)據(jù)庫(kù)

    TinyDB 是一個(gè)純 Python 編寫的輕量級(jí)數(shù)據(jù)庫(kù),一共只有1800行代碼,沒有外部依賴項(xiàng)。 TinyDB的目標(biāo)是降低小型 Python 應(yīng)用程序使用數(shù)據(jù)庫(kù)的難度,對(duì)于一些簡(jiǎn)單程序而言與其
    的頭像 發(fā)表于 10-21 10:22 ?896次閱讀

    Python運(yùn)行環(huán)境哪些

    ,也是最常用的解釋器。它是C語言編寫的,支持C的擴(kuò)展和嵌入。CPython可以在各個(gè)操作系統(tǒng)上運(yùn)行,并提供了Python的核心功能。 JPython: JPython是Python
    的頭像 發(fā)表于 11-29 16:14 ?1885次閱讀

    如何使用Python編寫腳本來自動(dòng)發(fā)送郵件

    Python是一種非常流行的編程語言,可以用于多種用途,包括自動(dòng)化任務(wù)。其中一個(gè)常見的自動(dòng)化任務(wù)是自動(dòng)發(fā)送郵件。在本文中,我們將介紹如何使用Python編寫腳本來自動(dòng)發(fā)送郵件。 要使用Pyth
    的頭像 發(fā)表于 12-07 11:36 ?1280次閱讀