在本章之前,python還沒有顯示出太突出的優勢。本章開始,讀者就會越來越感覺到python的強大了。這種強大體現在“模塊自信”上,因為python不僅有很強大的自有模塊(稱之為標準庫),還有海量的第三方模塊,任何人還都能自己開發模塊,正是有了這么強大的“模塊自信”,才體現了python的優勢所在。并且這種方式也正在不斷被更多其它語言所借鑒。
“模塊自信”的本質是:開放。
python不是一個封閉的體系,是一個開放系統。開放系統的最大好處就是避免了“熵增”。
> 熵的概念是由德國物理學家克勞修斯于1865年(這一年李鴻章建立了江南機械制造總局,美國廢除奴隸制,林肯總統遇刺身亡,美國南北戰爭結束。)所提出。是一種測量在動力學方面不能做功的能量總數,也就是當總體的熵增加,其做功能力也下降,熵的量度正是能量退化的指標。
>
> 熵亦被用于計算一個系統中的失序現象,也就是計算該系統混亂的程度。
>
> 根據熵的統計學定義, 熱力學第二定律說明一個孤立系統的傾向于增加混亂程度。換句話說就是對于封閉系統而言,會越來越趨向于無序化。反過來,開放系統則能避免無序化。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/219.md#回憶過去)回憶過去
在本教程的[《語句(1)》](https://github.com/qiwsir/StarterLearningPython/blob/master/121.md)中,曾經介紹了import語句,有這樣一個例子:
~~~
>>> import math
>>> math.pow(3,2)
9.0
~~~
這里的math就是一個模塊,用import引入這個模塊,然后可以使用模塊里面的函數,比如這個pow()函數。顯然,這里我們是不需要自己動手寫具體函數的,我們的任務就是拿過來使用。這就是模塊的好處:拿過來就用,不用自己重寫。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/219.md#模塊是程序)模塊是程序
這個標題,一語道破了模塊的本質,它就是一個擴展名為`.py`的python程序。我們能夠在應該使用它的時候將它引用過來,節省精力,不需要重寫雷同的代碼。
但是,如果我自己寫一個`.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系統的地址格式,如果讀者使用的windows系統,請寫你所保存的文件路徑。
~~~
>>> import pm
>>> pm.lang
'python'
~~~
本來在pm.py文件中,有一個變量`lang = "python"`,這次它作為模塊引入(注意作為模塊引入的時候,不帶擴展名),就可以通過模塊名字來訪問變量`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的文件?如果不是,你那個可能是外星人用的python。
> 解釋器,英文是:interpreter,港臺翻譯為:直譯器。在python中,它的作用就是將.py的文件轉化為.pyc文件,而.pyc文件是由字節碼(bytecode)構成的,然后計算機執行.pyc文件。關于這方面的詳細解釋,請參閱維基百科的詞條:[直譯器](http://zh.wikipedia.org/zh/%E7%9B%B4%E8%AD%AF%E5%99%A8)
不少人喜歡將這個世界簡化簡化再簡化。比如人,就分為好人還壞人,比如編程語言就分為解釋型和編譯型,不但如此,還將兩種類型的語言分別貼上運行效率高低的標簽,解釋型的運行速度就慢,編譯型的就快。一般人都把python看成解釋型的,于是就得出它運行速度慢的結論。不少人都因此上當受騙了,認為python不值得學,或者做不了什么“大事”。這就是將本來復雜的多樣化的世界非得劃分為“黑白”的結果。這種喜歡用“非此即彼”的思維方式考慮問題的現象可以說在現在很常見,比如一提到“日本人”,除了蒼老師,都該殺,這基本上是小孩子的思維方法,可惜在某個過度內大行其道。
世界是復雜的,“敵人的敵人就是朋友”是幼稚的,“一分為二”是機械的。當然,蒼老師是德藝雙馨的。
就如同剛才看到的那個.pyc文件一樣,當python解釋器讀取了.py文件,先將它變成由字節碼組成的.pyc文件,然后這個.pyc文件交給一個叫做python虛擬機的東西去運行(那些號稱編譯型的語言也是這個流程,不同的是它們先有一個明顯的編譯過程,編譯好了之后再運行)。如果.py文件修改了,python解釋器會重新編譯,只是這個編譯過程不是完全顯示給你看的。
我這里說的比較籠統,要深入了解python程序的執行過程,可以閱讀這篇文章:[說說Python程序的執行過程](http://www.cnblogs.com/kym/archive/2012/05/14/2498728.html)
總之,有了.pyc文件后,每次運行,就不需要從新讓解釋器來編譯.py文件了,除非.py文件修改了。這樣,python運行的就是那個編譯好了的.pyc文件。
是否還記得,我們在前面寫有關程序,然后執行,常常要用到`if __name__ == "__main__"`。那時我們寫的.py文件是來執行的,這時我們同樣寫了.py文件,是作為模塊引入的。這就得深入探究一下,同樣是.py文件,它是怎么知道是被當做程序執行還是被當做模塊引入?
為了便于比較,將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'
~~~
因為這時候pm.py中的函數lang()就是一個屬性:
~~~
>>> dir(pm)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'lang']
~~~
同樣一個.py文件,可以把它當做程序來執行,還可以將它作為模塊引入。
~~~
>>> __name__
'__main__'
>>> pm.__name__
'pm'
~~~
如果要作為程序執行,則`__name__ == "__main__"`;如果作為模塊引入,則`pm.__name__ == "pm"`,即變量`__name__`的值是模塊名稱。
用這種方式就可以區分是執行程序還是作為模塊引入了。
在一般情況下,如果僅僅是用作模塊引入,可以不寫`if __name__ == "__main__"`。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/219.md#模塊的位置)模塊的位置
為了讓我們自己寫的模塊能夠被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']
~~~
從中也發現了我們自己寫的那個文件。凡在上面列表所包括位置內的.py文件都可以作為模塊引入。不妨舉個例子。把前面自己編寫的pm.py文件修改為pmlib.py,然后把它復制到`'/usr/lib/python2.7/dist-packages`中。(這是以ubuntu為例說明,如果是其它操作系統,讀者用類似方法也能找到。)
~~~
$ 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
~~~
文件放到了指定位置。看下面的:
~~~
>>> import pmlib
>>> pmlib.lang
<function lang at 0xb744372c>
>>> pmlib.lang()
'python'
~~~
也就是,要將模塊文件放到合適的位置——就是sys.path包括位置——就能夠直接用import引入了。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/219.md#pythonpath環境變量)PYTHONPATH環境變量
將模塊文件放到指定位置是一種不錯的方法。當程序員都喜歡自由,能不能放到別處呢?當然能,用`sys.path.append()`就是不管把文件放哪里,都可以把其位置告訴python解釋器。但是,這種方法不是很常用。因為它也有麻煩的地方,比如在交互模式下,如果關閉了,然后再開啟,還得從新告知。
比較常用的告知方法是設置PYTHONPATH環境變量。
> 環境變量,不同操作系統的設置方法略有差異。讀者可以根據自己的操作系統,到網上搜索設置方法。
我以ubuntu為例,建立一個python的目錄,然后將我自己寫的.py文件放到這里,并設置環境變量。
~~~
:~$ mkdir python
:~$ cd python
:~/python$ cp ~/Documents/VBS/StarterLearningPython/2code/pm.py mypm.py
:~/python$ ls
mypm.py
~~~
然后將這個目錄`~/python`,也就是`/home/qw/python`設置環境變量。
~~~
vim /etc/profile
~~~
提醒要用root權限,在打開的文件最后增加`export PATH = /home/qw/python:$PAT`,然后保存退出即可。
注意,我是在`~/python`目錄下輸入`python`,進入到交互模式:
~~~
:~$ cd python
:~/python$ python
>>> import mypm
>>> mypm.lang()
'python'
~~~
如此,就完成了告知過程。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/219.md#__init__py方法)`__init__.py`方法
`__init__.py`是一個空文件,將它放在某個目錄中,就可以將該目錄中的其它.py文件作為模塊被引用。這個具體應用參見[用tornado做網站(2)](https://github.com/qiwsir/StarterLearningPython/blob/master/304.md)
- 第零章 預備
- 關于Python的故事
- 從小工到專家
- Python安裝
- 集成開發環境
- 第壹章 基本數據類型
- 數和四則運算
- 除法
- 常用數學函數和運算優先級
- 寫一個簡單的程序
- 字符串(1)
- 字符串(2)
- 字符串(3)
- 字符串(4)
- 字符編碼
- 列表(1)
- 列表(2)
- 列表(3)
- 回顧list和str
- 元組
- 字典(1)
- 字典(2)
- 集合(1)
- 集合(2)
- 第貳章 語句和文件
- 運算符
- 語句(1)
- 語句(2)
- 語句(3)
- 語句(4)
- 語句(5)
- 文件(1)
- 文件(2)
- 迭代
- 練習
- 自省
- 第叁章 函數
- 函數(1)
- 函數(2)
- 函數(3)
- 函數(4)
- 函數練習
- 第肆章 類
- 類(1)
- 類(2)
- 類(3)
- 類(4)
- 類(5)
- 多態和封裝
- 特殊方法(1)
- 特殊方法(2)
- 迭代器
- 生成器
- 上下文管理器
- 第伍章 錯誤和異常
- 錯誤和異常(1)
- 錯誤和異常(2)
- 錯誤和異常(3)
- 第陸章 模塊
- 編寫模塊
- 標準庫(1)
- 標準庫(2)
- 標準庫(3)
- 標準庫(4)
- 標準庫(5)
- 標準庫(6)
- 標準庫(7)
- 標準庫(8)
- 第三方庫
- 第柒章 保存數據
- 將數據存入文件
- mysql數據庫(1)
- MySQL數據庫(2)
- mongodb數據庫(1)
- SQLite數據庫
- 電子表格
- 第捌章 用Tornado做網站
- 為做網站而準備
- 分析Hello
- 用tornado做網站(1)
- 用tornado做網站(2)
- 用tornado做網站(3)
- 用tornado做網站(4)
- 用tornado做網站(5)
- 用tornado做網站(6)
- 用tornado做網站(7)
- 第玖章 科學計算
- 為計算做準備
- Pandas使用(1)
- Pandas使用(2)
- 處理股票數據
- 附:網絡文摘
- 如何成為Python高手
- ASCII、Unicode、GBK和UTF-8字符編碼的區別聯系