python學習筆記之九:模塊和包


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結尾的文件即可。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM