文章目錄
- 1、位元組編譯的.pyc檔案
- 2、from ... import ...語句
- 3、模組的__name__屬性
- 4、建立自己的模組
- 5、dir()函數
- 6、包(Packages)
七、模組:
我們可以通過編寫函數來複用代碼,同樣我們可以通過模組來複用大量函數。有多重方法可以編寫模組,但是最簡單的方法是建立一個以.py為尾碼的檔案來包含需要複用的變數和函數。另一種方式是以編寫python解譯器的本地語言編寫模組。例如C語言編寫的模組被編譯後可供運行於標準python解譯器上的python代碼使用。模組可以被其它程式匯入以使用其提供的功能。這也是為什麼我們可以使用python標準庫。
我們先來看看如何使用標準庫模組:
# Filename: using_sys.py import sys print('The command line arguments are:')for i in sys.argv: print(i) print('\n\nThe PYTHONPATH is', sys.path, '\n')
輸出:
C:\Users\Administrator>python D:\python\using_sys.py we are arguments
The command line arguments are:
D:\python\using_sys.py
we
are
arguments
The PYTHONPATH is ['D:\\python', 'C:\\Windows\\system32\\python32.zip', 'C:\\Pyt
hon32\\DLLs', 'C:\\Python32\\lib', 'C:\\Python32', 'C:\\Python32\\lib\\site-pack
ages']
首先我們使用import語句匯入sys模組。本質上這告訴python我們希望使用這個模組。sys模組包含python解譯器與其工作環境(即系統)相關的功能。
當python執行import sys語句時,它將尋找sys模組。本例中sys是內建模組之一,因此python知道在哪能找到它。 如果匯入的不是一個編譯模組,即不是用python編寫的模組,python解譯器會在變數sys.path中列出的目錄中尋找它。 如果模組被找到,這個模組中的語句將被執行然後你就可以使用它了(注: 只有頂級語句才會執行,也就是主塊中的語句)。
注意一個模組只有在第一次匯入時會被初始化。
sys模組中的argv通過點號引用即sys.argv。它清晰的指出這個名字是sys模組中的一部分。這種文法的另一個優勢是不會和你的程式中的同名argv變數發生衝突。 變數sys.argv是一個字串列表(後章會詳細解釋列表)。具體說sys.argv是一個包含命令列參數的列表,也就是使用命令列傳遞給你的程式的參數。 如果你在使用IDE編寫程式,請在菜單中尋找為程式指定命令列參數的方法。
這裡,當我們執行python using_sys.py we are arguments時,我們以python命令運行using_sys.py模組,其後的內容是傳遞給程式的參數。python將它們存到sys.argv以供我們使用。
注意:被運行指令碼的指令碼名永遠是sys.argv的第一個參數。
所以本例中sys.argv[0]為’using_sys.py’,sys.argv[1]為’we’,sys.argv[2]是’are’, argv[3]是’arguments’。注意python下標從0開始而非1。 sys.path包含一個目錄名列表指示從哪裡匯入模組。
1、位元組編譯的.pyc檔案
輸入一個模組相對來說是一個比較費時的事情,所以Python做了一些技巧,以便使輸入模組更加快一些。一種方法是建立位元組編譯的檔案,這些檔案以.pyc作為副檔名。位元組編譯的檔案與Python變換程式的中間狀態有關。當你在下次從別的程式輸入這個模組的時候,.pyc檔案是十分有用的——它會快得多,因為一部分輸入模組所需的處理已經完成了。另外,這些位元組編譯的檔案也是與平台無關的。
注意:.pyc檔案一般被建立在與其對應的.py檔案所在的相同目錄下。如果python沒有這個目錄的寫入權限,則.pyc檔案不會被建立。
2、from ... import ...語句
如果你想要直接輸入argv變數到你的程式中(避免在每次使用它時打sys.),那麼你可以使用from sys import argv語句。如果你想要輸入所有sys模組使用的名字,那麼你可以使用from sys import *語句。這對於所有模組都適用。一般說來,應該避免使用from..import而使用import語句,因為這樣可以使你的程式更加易讀,也可以避免名稱的衝突。
例如:
from math import * n = input("Enter range:- ")p = [2, 3]count = 2a = 5while(count < n):b = 0for i in range(2, a):if(i <= sqrt(a)):if(a % i == 0):#print a, "is not a prime" b = 1else:passif(b != 1):#print a, "is a prime"p = p + [a]count = count + 1a = a + 2print p
3、模組的__name__屬性
每個模組都有一個名字,並且通過模組中的某些語句可以得到這個模組名。在一些想要搞清模組是獨立運行還是被匯入的情況下,這會非常方便。如前所述當模組第一次被匯入時模組中的代碼會被執行。我們可以據此改變模組獨立執行時的行為方式。這可以通過模組的__name__屬性做到。
例如:
運行第二個Import語句前把檔案複製一份到python目錄下才可以正常運行
# Filename: using_name.py if __name__ == '__main__': print('This program is being run by itself')else: print('I am being imported from another module')
輸出:
C:\Users\Administrator>python D:\python\using_name.py
This program is being run by itself C:\Users\Administrator>python
Python 3.2.2 (default, Sep 4 2011, 09:51:08) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import using_name
I am being imported from another module
工作原理:
每個python模組都有自己的__name__定義,如果它是'__main__’則暗示模組為獨立運行,我們可以進行一些適當的處理。
4、建立自己的模組
建立你自己的模組很簡單,其實你一直在這樣做!因為每個python指令碼都是一個模組。你只需確保它帶有.py副檔名即可。
下面的例子會讓你對其有一個清晰的認識:
# Filename: mymodule.py def sayhi(): print('Hi, this is mymodule speaking.') __version__ = '0.1' # End of mymodule.py
上面就是一個簡單的模組,如你所見,這和我們平時的python程式相比沒有什麼特別之處。
記住模組應該放到匯入它的那個程式所在的目錄下,或者放到sys.path列出的目錄之一中。
# Filename: mymodule_demo.py import mymodule mymodule.sayhi()print ('Version', mymodule.__version__)
輸出:
C:\Users\Administrator>python D:\python\mymodule_demo.py
Hi, this is mymodule speaking.
Version 0.1
注意我們同樣使用點號訪問模組成員。python很好的重複利用了相同的符號,帶來獨特的’Pythonic’感受,這樣我們就不必學習更多的文法知識了。
下面是一個使用from..import
文法的版本:
# Filename: mymodule_demo2.py from mymodule import sayhi, __version__ sayhi()print('Version', __version__)
mymodule_demo2.py
的輸出與mymodule_demo.py
完全相同。
注意,如果匯入mymodule的模組中已經存在同名的__version__,則將發生名字衝突。其實上這很可能發生,因為每個模組都用__version__聲明它的版本是一種常見的做法。因此建議你優先考慮import語句,雖然它可能會讓你的程式變的更長一些。
你同樣可以使用:from mymodule import *,這將匯入模組的所有公有名字,例如sayhi,但是不會匯入__version__因為它以雙底線開頭。
5、dir()函數
你可以使用dir函數列出一個對象定義的所有標識符。例如對於一個模組,標識符包括函數,類,變數。當你為dir()函數提供一個模組名,它將返回定義在其中的所有名字。當dir()的參數為空白時,返回定義在當前模組中所有名字。
例如:
C:\Users\Administrator>pythonPython 3.2.2 (default, Sep 4 2011, 09:51:08) [MSC v.1500 32 bit (Intel)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> dir(sys)['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_compact_freelists','_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable','exit', 'flags', 'float_info', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'gettrace', 'getwindowsversion', 'hexversion', 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptions', 'winver'] >>> dir() # get list of attributes for current module['__builtins__', '__doc__', '__name__', '__package__', 'sys'] >>> a = 5 # create a new variable 'a' >>> dir()['__builtins__', '__doc__', '__name__', '__package__', 'a', 'sys'] >>> del a # delete/remove a name >>> dir()['__builtins__', '__doc__', '__name__', '__package__', 'sys']
工作原理:
首先,我們通過被匯入的sys模組應用dir函數. 可以看到sys包含巨多的屬性。
接下來,我們不為dir函數提供參數。預設的它返回當前模組的屬性列表。注意被匯入模組列表也是當前模組列表的一部分。
為了觀察到dir確定起作用了,我們定義一個新變數a並為其賦值然後檢驗dir的傳回值,我們發現在返回的列表中確實出現了一個與變數a同名的值。在我們使用del語句刪除當前模組的變數/屬性後,改變再次反映到了dir函數的輸出上。
del註解 – 這個語句用於刪除一個變數/名字,在本例中,del a之後你就無法訪問變數a了 – 就像它從來沒有存在過一樣。
注意dir()函數可用於任何對象。例如執行dir (print)學習更多關於print函數的屬性,或是dir(str)列出str類的屬性。
6、包(Packages)
現在,你必須開始留心組織你的程式層次了。
變數在函數內部,函數和全域變數通常在模組內部。那麼如何組織模組呢?這就輪到包登場了。包僅僅是包含模組的檔案夾,並帶有一個特殊的檔案__init__.py用於指示python這個檔案夾是特殊的,因為它包含python模組。讓我們假設你需要建立一個叫做’world’的包,裡麵包括諸如’asia’,‘africa’等的子包。
下面告訴你應該如何組織檔案夾結構:
- <some folder present in the sys.path>/ - world/ - __init__.py - asia/ - __init__.py - india/ - __init__.py - foo.py - africa/ - __init__.py - madagascar/ - __init__.py - bar.py
包只是用來有層次的組織模組。你會在標準庫中看到它的很多應用。