翻譯:《實用的Python編程》03_04_Modules

目錄 | 上一節 (3.3 錯誤檢查) | 下一節 (3.5 主模塊)html

3.4 模塊

本節介紹模塊的概念以及如何使用跨多個文件的函數。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 語句仍加載所有的數學模塊。當導入完成後,它僅僅將模塊中的 cossin 名稱複製到局部命名空間中。

模塊加載

每一個模塊僅加載和執行一次。注意:重複導入僅返回先前所加載模塊的引用

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.11:模塊導入

在第 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 ...
>>>

練習 3.12:使用庫模塊

在第 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() 函數。

在本練習開始時,請使用交互示例做爲指南。以後,應該可以得到與以前徹底相同的輸出。

練習 3.14:使用更多的庫導入

在第 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 程序。

目錄 | 上一節 (3.3 錯誤檢查) | 下一節 (3.5 主模塊)

注:完整翻譯見 https://github.com/codists/practical-python-zh

相關文章
相關標籤/搜索