一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

跟老齊學Python之自己編寫模塊

 星光閃亮圖書館 2018-04-04


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

“模塊自信”的本質是:開放。

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

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

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

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

編寫模塊

想必讀者已經熟悉了import語句,曾經有這樣一個例子:

>>> import math

>>> math.pow(3,2)

9.0

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

1.  模塊是程序

“模塊是程序”一語道破了模塊的本質,它就是一個擴展名為.py的Python程序。

我們能夠在應該使用它的時候將它引用過來,節(jié)省精力,不需要重寫雷同的代碼。

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

#!/usr/bin/env python

# coding=utf-8

lang = "python"

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

>>> import sys

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

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

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

>>> import pm

>>> pm.lang

'python'

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

>>> pm.xx

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

AttributeError: 'module' object has no attribute 'xx'

請讀者回到pm.py文件的存儲目錄,查看一下是不是多了一個擴展名是.pyc的文件?

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

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

世界是復雜的,“敵人的敵人就是朋友”是幼稚的,“一分為二”是機械的。

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

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

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

為了便于比較,將pm.py文件進行改造。

#!/usr/bin/env python

# coding=utf-8


def lang():

    return "python"


if __name__ == "__main__":

    print lang()

沿用先前的做法:

$ python pm.py

python

如果將這個程序作為模塊,導入,會是這樣的:

>>> import sys

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

>>> import pm

>>> pm.lang()

'python'

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

>>> dir(pm)

['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'lang']

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

>>> __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")。其實,在Python中,所有模塊都被加入到了sys.path里面。用下面的方法可以看到模塊所在位置:

>>> import sys

>>> import pprint

>>> pprint.pprint(sys.path)

['',

 '/usr/local/lib/python2.7/dist-packages/autopep8-1.1-py2.7.egg',

 '/usr/local/lib/python2.7/dist-packages/pep8-1.5.7-py2.7.egg',

 '/usr/lib/python2.7',

 '/usr/lib/python2.7/plat-i386-linux-gnu',

 '/usr/lib/python2.7/lib-tk',

 '/usr/lib/python2.7/lib-old',

 '/usr/lib/python2.7/lib-dynload',

 '/usr/local/lib/python2.7/dist-packages',

 '/usr/lib/python2.7/dist-packages',

 '/usr/lib/python2.7/dist-packages/PILcompat',

 '/usr/lib/python2.7/dist-packages/gtk-2.0',

 '/usr/lib/python2.7/dist-packages/ubuntu-sso-client',

 '~/Documents/VBS/StarterLearningPython/2code/pm.py']

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

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

$ sudo cp pm.py /usr/lib/python2.7/dist-packages/pmlib.py

[sudo] password for qw:


$ ls /usr/lib/python2.7/dist-packages/pm*

/usr/lib/python2.7/dist-packages/pmlib.py

文件放到了指定位置??聪旅娴模?/p>

>>> import pmlib

>>> pmlib.lang

<function lang at 0xb744372c>

>>> pmlib.lang()

'python'

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

當然能,用sys.path.append()就是不管把文件放在哪里,都可以把其位置告訴Python解釋器。雖然這種方法在前面用了,但其實是很不常用的,因為它也有麻煩的地方,比如在交互模式下,如果關閉了,再開啟,還得重新告知。

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

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

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

:~$ mkdir python

:~$ cd python

:~/python$ cp ~/Documents/VBS/StarterLearningPython/2code/pm.py mypm.py

:~/python$ ls

mypm.py

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

vim /etc/profile

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

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

:~$ cd python

:~/python$ python


>>> import mypm

>>> mypm.lang()

'python'

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

3.  __all__在模塊中的作用

上面的模塊雖然比較簡單,但是已經顯示了編寫模塊,以及在程序中導入模塊的基本方式。在實踐中,所編寫的模塊也許更復雜一點,比如,有這么一個模塊,其文件命名為pp.py

# /usr/bin/env python

# coding:utf-8


public_variable = "Hello, I am a public variable."

_private_variable = "Hi, I am a private variable."


def public_teacher():

    print "I am a public teacher, I am from JP."


def _private_teacher():

    print "I am a private teacher, I am from CN."

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

>>> import sys

>>> sys.path.append("~/Documents/StarterLearningPython/2code/pp.py")

>>> import pp

>>> from pp import *

>>> public_variable

'Hello, I am a public variable.'

>>> _private_variable

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

NameError: name '_private_variable' is not defined

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

再如:

>>> public_teacher()

  I am a public teacher, I am from JP.

>>> _private_teacher()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

NameError: name '_private_teacher' is not defined

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

>>> import pp

>>> pp._private_teacher()

I am a private teacher, I am from CN.

>>> pp._private_variable

'Hi, I am a private variable.'

下面再對pp.py文件進行改寫,增加一些東西。

# /usr/bin/env python

# coding:utf-8


__all__ = ['_private_variable', 'public_teacher']


public_variable = "Hello, I am a public variable."

_private_variable = "Hi, I am a private variable."


def public_teacher():

    print "I am a public teacher, I am from JP."


def _private_teacher():

        print "I am a private teacher, I am from CN."

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

>>> import sys

>>> sys.path.append("~/Documents/StarterLearningPython/2code/pp.py")

>>> from pp import *

>>> _private_variable

'Hi, I am a private variable.'

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

>>> public_variable

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

NameError: name 'public_variable' is not defined

因為這個變量沒有在__all__的值中,雖然以前曾經被訪問到過,但是現(xiàn)在就不行了。

>>> public_teacher()

I am a public teacher, I am from JP.

>>> _private_teacher()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

NameError: name '_private_teacher' is not defined

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

4.  包和庫

顧名思義,包和庫都是比“模塊”大的。一般來講,一個“包”里面會有多個模塊,當然,“庫”是一個更大的概念了,比如Python標準庫中的每個庫都有好多個包,每個包都有若干個模塊。

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

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

接下來,需要導入這個包(package_qi)中的模塊。

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

>>> import package_qi.pm

>>> package_qi.pm.lang()

'python'

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

>>> from package_qi import pm

>>> pm.lang()

'python'

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

書籍介紹:

本書是面向編程零基礎讀者的Python入門教程,內容涵蓋了Python的基礎知識和初步應用。以比較輕快的風格,向零基礎的學習者介紹一門時下比較流行、并且用途比較廣泛的編程語言,所以,本書讀起來不晦澀,并且在其中穿插了很多貌似與Python編程無關,但與學習者未來程序員職業(yè)生涯有關的內容。 本書特別強調了學習和使用Python的基本方法,學習一種高級語言,掌握其各種規(guī)則是必要的,但學會“自省”方法更重要,這也是本書所試圖達到的“授人以魚不如授人以漁”的目的。

如果Google已經不能解決你的問題,如果你想獲取頂級架構師的非公開實踐,如果你想學習100+海內外的私密架構案例,戳這里,即刻8折報名ArchSummit全球架構師峰會[深圳站]

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    99国产一区在线播放| 免费特黄一级一区二区三区| 日本加勒比中文在线观看| 久久三级国外久久久三级| 激情五月天深爱丁香婷婷| 国产又猛又黄又粗又爽无遮挡| 中文字幕人妻日本一区二区| 日本精品免费在线观看| 美女极度色诱视频在线观看| av免费视屏在线观看| 亚洲一区二区三区日韩91| 国产精品一区二区视频| 欧美日韩三区在线观看| 亚洲国产性感美女视频| 欧美日本精品视频在线观看| 欧美一区二区口爆吞精| 午夜福利精品视频视频| 亚洲熟妇熟女久久精品| 国产在线一区中文字幕| 亚洲熟女诱惑一区二区| 婷婷亚洲综合五月天麻豆| 国产在线一区二区三区不卡| 欧美日韩国产精品黄片| 国产又长又粗又爽免费视频| 亚洲免费黄色高清在线观看| 午夜精品成年人免费视频| 国产白丝粉嫩av在线免费观看| 暴力性生活在线免费视频| 亚洲国产精品一区二区| 国产精品久久香蕉国产线| 久久永久免费一区二区| 丰满人妻熟妇乱又伦精另类视频 | 亚洲在线观看福利视频| 肥白女人日韩中文视频| 欧美黄色黑人一区二区| 欧美区一区二在线播放| 超薄丝袜足一区二区三区| 日韩毛片视频免费观看| 噜噜中文字幕一区二区| 国产成人精品在线一区二区三区| 欧美日韩综合在线精品|