Python的標准安裝包括一組模塊,稱為標准庫。這里介紹模塊的工作方式,學習如何使用它們。
一. 模塊
1.1 用import從外部模塊獲取函數並為自己的程序所用:
>>> from math import sqrt >>> import math
1.2 編寫自己的模塊
任何python程序都可以作為模塊導入。程序保存的位置很重要。假設我們所寫的程序叫hello.py被保存在c:/python目錄下,可以執行以下的代碼,告訴解釋器在哪里尋找hello.py模塊:
#hello.py
print "hello,world!"
>>> import sys >>> sys.path.append('c:/python')
>>> import hello
hello,world!
如上所見,在導入模塊時,其中的代碼被執行了。不過如果再次導入該模塊,就什么都不會發生了。因為導入模塊並不意味着在導入時執行某些操作,它們主要用於定義,只需要定義一次,導入模塊一次和多次的效果是一樣的。
1.3 模塊用於定義
導入模塊真正的用處在於保持自己的作用域,這意味着定義的所有類和函數以及賦值后的變量都成了模塊的特性。
(1)我們可以在模塊底下定義函數,然后像標准庫那樣導入它們。
(2)我們還可以在模塊中增加測試代碼來檢查模塊本身是否正常工作:
有2種辦法加入測試代碼:
第一種辦法是“告知”模塊本身是作為程序運行還是導入到其他程序:
#hello.py def hello(): print 'hello:__name__' #A test: hello() >>> __name__ '__main__' >>> hello.__name__ 'hello:__name__'
第二種辦法是使用條件測試代碼:
#hello.py def hello(): print 'hello' #A test: def test(): hello() if __name__ == '__main__':test()
這樣如果將它作為程序運行,hello()函數會被執行,而作為模塊導入時,它的行為就會像普通模塊一樣。
1.4 讓模塊可用
(1)把模塊放在正確的位置:只需找出python解釋器從哪里開始查找模塊,然后將你自己的文件放置在那里即可。
>>> import sys >>> print sys.path ['D:\\python', 'C:\\Python27\\Lib\\idlelib', 'C:\\Python27\\python27.zip', 'C:\\Python27\\DLLs', 'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\\Python27\\lib\\lib-tk', 'C:\\Python27', 'C:\\Python27\\lib\\site-packages']
以上目錄都可以用來存放我們定義的文件,但是site-packages目錄是最佳選擇,因為它就是用來做這些事情的。
(2)告訴編譯器哪里去找:編輯sys.path或者是在PYTHONPATH環境變量中包含模塊所在目錄
二. 包package
為了組織好模塊,你可以把它們分組為包。當模塊存儲在文件.py中時,包就是模塊所在的目錄。
為了讓python將其作為包對待,它必須包含一個名為__init__.py的文件。
如果要建立一個叫dd的包,其中包含aa和cc的模塊,那么你就需要創建如下文件和目錄:
1. D:/pythons 2. D:/pythons/dd 3. D:/python/sdd/__init__.py 4. D:/python/sdd/aa.py 5. D:/pythonsdd/cc.py
(以上假設D:/pythons已經被放置到PYTHONPATH中。)
import dd # __init__中的內容可用,aa和cc模塊不可用 import dd.aa #aa模塊可用了,但只能使用全名dd.aa來使用 from dd import cc #cc模塊可用了,可用通過短名cc來使用
三. 探究模塊
學會如何探究模塊是極有價值的技能。探究模塊最直接的方式是在python解釋器中研究它們。
3.1 模塊中有什么 -- 比如copy標准模塊
(1)使用dir函數
使用dir函數可以將對象的特性都列出,如下,我們可以使用列表推導式過濾掉一部分:
>>> import copy >>> [n for n in dir(copy) if not n.startswith('_')] ['Error', 'PyStringMap', 'copy', 'deepcopy', 'dispatch_table', 'error', 'name', 't', 'weakref']
>>> [n for n in dir(copy) if n.startswith('__')]
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__']
(2)繼續查看它的__all__
>>> copy.__all__ ['Error', 'copy', 'deepcopy']
可見它定義了模塊的公有借口,更准確地說,它告訴解釋器:從模塊導入所有名字代表什么含義。
如:from cpy import *意味着你只能使用__all__變量中的幾個函數,如果要導入PyStringMap的話,就要這樣做:
導入copy然后使用copy.PyStringMap;或者是使用from copy import PyStringMap
我們在編寫模塊的時候,像設置__all__這樣的技術是相當有用的,因為一個模塊中可能會有一大堆其他程序不需要或者不想要的變量,函數和類,__all__會把它們過濾出去。如果沒有設定__all__,用import*會默認輸出模塊中所有不以下划線開頭的全局名稱。
3.2 用help函數獲取幫助
help函數能夠為你提供日常所需的信息:
>>> help(copy) Help on module copy: NAME copy - Generic (shallow and deep) copying operations. FILE c:\python27\lib\copy.py DESCRIPTION Interface summary: import copy x = copy.copy(y) # make a shallow copy of y x = copy.deepcopy(y) # make a deep copy of y .......
3.3 文檔--模塊信息的自然來源
比如尋找range的文檔描述:
>>> print range.__doc__ range(stop) -> list of integers range(start, stop[, step]) -> list of integers Return a list containing an arithmetic progression of integers. range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0. When step is given, it specifies the increment (or decrement). For example, range(4) returns [0, 1, 2, 3]. The end point is omitted! These are exactly the valid indices for a list of 4 elements.
這樣就獲得了關於range函數的精確描述。但是要記住,並不是所有的模塊和函數都有不錯的文檔字符串的,有時候要透徹理解模塊和函數是如何工作的,最好參考Pyhton庫:http:python.org/doc/lib
3.4 使用源代碼
使用如下語句就可以查找到想要模塊的源代碼位置:
>>> print copy.__file__ C:\Python27\lib\copy.pyc
如果文件名以.pyc結尾,只要查看相應的以.py結尾的文件即可。
