目錄 | 上一節 (3.3 錯誤檢查) | 下一節 (3.5 主模塊)html
本節介紹模塊的概念以及如何使用跨多個文件的函數。python
任何一個 Python 源文件都是一個模塊。git
# foo.py def grok(a): ... def spam(b): ...
import
語句加載並執行一個模塊。github
# program.py import foo a = foo.grok(2) b = foo.spam('Hello') ...
模塊是命名值的集合,有時也稱爲命名空間。名稱是源文件中定義的全部全局變量和函數。導入以後,模塊名稱用做前綴。所以,稱爲命名空間。shell
import foo a = foo.grok(2) b = foo.spam('Hello') ...
模塊名直接綁定到文件名(foo -> foo.py)。編程
填充模塊命名空間的內容是定義在全局(global)做用域中任何內容。考慮定義了相同變量 x 的兩個模塊。緩存
# foo.py x = 42 def grok(a): ...
# bar.py x = 37 def spam(a): ...
在本例中,x
指向不一樣的變量。一個是 foo.x
,另外一個是 bar.x
。不一樣的模塊可使用相同的名稱而且這些名稱不會相互衝突。安全
模塊是隔離的。bash
對於全部定義在模塊裏面的代碼而言,模塊構成一個封閉的環境。app
# foo.py x = 42 def grok(a): print(x)
全局變量始終綁定到封閉模塊(相同文件),每一個源文件都是它本身的小宇宙。
導入模塊時,模塊中的全部語句依次執行(execute),直到到達文件末尾。模塊命名空間的內容是全部的全局名稱,這些名稱在執行過程結束時仍然被定義。若是有腳本語句在全局做用域中執行任務(如打印,建立文件等),您將看到它們在導入模塊時運行。
import as
語句能夠在導入模塊時更改其名稱:
import math as m def rectangular(r, theta): x = r * m.cos(theta) y = r * m.sin(theta) return x, y
它的做用與普通導入相同,僅僅是重命名模塊而已。
from import
語句from import
語句從模塊中選出符號並使它們在局部可訪問。
from math import sin, cos def rectangular(r, theta): x = r * cos(theta) y = r * sin(theta) return x, y
這容許使用模塊的某些部分,而沒必要輸入模塊前綴。對於常用的名稱,這很是有用。
有關導入的各類變化不改變模塊的工做方式。
import math # vs import math as m # vs from math import cos, sin ...
具體來講,import
始終執行整個文件而且模塊仍然是隔離的環境。
import module as
語句只局部地更更名稱。在後臺,from math import cos, sin
語句仍加載所有的數學模塊。當導入完成後,它僅僅將模塊中的 cos
和 sin
名稱複製到局部命名空間中。
每一個模塊僅加載和執行一次。注意:重複導入僅返回先前所加載模塊的引用
sys.modules
是全部已加載模塊的字典。
>>> import sys >>> sys.modules.keys() ['copy_reg', '__main__', 'site', '__builtin__', 'encodings', 'encodings.encodings', 'posixpath', ...] >>>
注意:當修改模塊的源代碼後,若是重複import
語句會產生一個常見的困惑。因爲模塊緩存 sys.modules
,重複導入老是返回以前加載的模塊——即便更改已經發生。將修改後的代碼加載到 Python 中最安全的方式是退出而後重啓解釋器。
搜索模塊時,Python 從路徑列表(sys.path)中查詢。
>>> import sys >>> sys.path [ '', '/usr/local/lib/python36/python36.zip', '/usr/local/lib/python36', ... ]
當前工做目錄一般是第一個。
如前所述,sys.path
包含搜索路徑。能夠根據須要手動調整 。
import sys sys.path.append('/project/foo/pyfiles')
也能夠經過環境變量添加搜索路徑。
% env PYTHONPATH=/project/foo/pyfiles python3 Python 3.6.0 (default, Feb 3 2017, 05:53:21) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] >>> import sys >>> sys.path ['','/project/foo/pyfiles', ...]
在大部分狀況下,不必手動調整模塊搜索路徑。可是,若是嘗試導入的 Python 代碼位於特殊位置,或者沒法從當前工做目錄輕鬆訪問,那麼就須要手動調整搜索路徑了。
由於本練習涉及模塊,因此確保在適當的環境中運行 Python 相當重要。模塊常常給編程新手帶來問題,這些問題與當前工做目錄相關或者與 Python 路徑設置相關。對於本課程,假定您是在 Work/
目錄下編寫全部的代碼。爲了得到最佳結果,應該確保也是在 Work/
目錄下運行解釋器。不然,須要確保 practical-python/Work
已添加到 sys.path
。
在第 3 節中,咱們建立了一個通用目標函數 parse_csv()
用於解析 CSV 數據文件的內容。
如今,咱們來看看如何在其它程序中使用該函數。首先,啓動一個新的 shell 窗口,進入到放置全部文件的目錄中。咱們將要導入它們。
啓動 Python 交互模式。
bash % python3 Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04) [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>>
當Python 交互模式啓動後,嘗試導入某些以前編寫的程序。應該能看到輸出和之前同樣。強調一下,導入模塊會運行模塊中的代碼。
>>> import bounce ... watch output ... >>> import mortgage ... watch output ... >>> import report ... watch output ... >>>
若是沒有代碼運行,多是由於在錯誤的目錄下運行了 Python。如今,嘗試導入 fileparse
模塊並獲取有關該模塊的幫助。
>>> import fileparse >>> help(fileparse) ... look at the output ... >>> dir(fileparse) ... look at the output ... >>>
嘗試使用 fileparse
模塊來讀取一些數據:
>>> portfolio = fileparse.parse_csv('Data/portfolio.csv',select=['name','shares','price'], types=[str,int,float]) >>> portfolio ... look at the output ... >>> pricelist = fileparse.parse_csv('Data/prices.csv',types=[str,float], has_headers=False) >>> pricelist ... look at the output ... >>> prices = dict(pricelist) >>> prices ... look at the output ... >>> prices['IBM'] 106.11 >>>
嘗試導入一個函數,以便不用再包含模塊名:
>>> from fileparse import parse_csv >>> portfolio = parse_csv('Data/portfolio.csv', select=['name','shares','price'], types=[str,int,float]) >>> portfolio ... look at the output ... >>>
在第 2 節中,編寫了 report.py
程序用來生成像下面這樣的股票報告:
Name Shares Price Change ---------- ---------- ---------- ---------- AA 100 9.22 -22.98 IBM 50 106.28 15.18 CAT 150 35.46 -47.98 MSFT 200 20.89 -30.34 GE 95 13.48 -26.89 MSFT 50 20.89 -44.21 IBM 100 106.28 35.84
使用該程序並對其進行修改,以便使用 fileparse
模塊中的函數完成全部輸入文件的處理。爲此,將 fileparse
做爲模塊導入,並修改 read_portfolio()
和 read_prices()
函數以便使用 parse_csv()
函數。
在本練習開始時,請使用交互示例做爲指南。以後,應該可以得到與以前徹底相同的輸出。
在第 1 節中,編寫了一個讀取股票投資組合和計算費用的程序 pcost.py
。
>>> import pcost >>> pcost.portfolio_cost('Data/portfolio.csv') 44671.15 >>>
請修改 pcost.py
文件,以便它可以使用 report.read_portfolio()
函數。
當完成練習後,您應該擁有三個程序。包含通用目的函數 parse_csv()
的fileparse.py
程序。用於生成報告,且包含 read_portfolio()
和 read_prices()
函數的 report.py
程序。最後,利用 report.py
程序中編寫的read_portfolio()
函數去計算股票投資組合費用的 pcost.py
程序。