第十三章 模組和包

weixin_33907511發表於2019-01-02

模組化程式設計

Python 有時候稱為膠水語言,就是因為它有強大的可擴充套件性,這個擴充套件性就是用模組實現的。

模組其實就是一個以 .py 結尾的 Python 檔案,這個檔案中可以包含變數、函式、類等。

這個模組可以包含實現了一個或者多個功能的程式碼。

模組可以在其他 Python 檔案中使用,可以通過網路進行傳播。

這樣的話,如果想在你的程式中實現某些功能,其實網路的其他程式猿已經給你寫好了,下載下來,安裝到自己的環境下,就可以使用了。

模組化程式設計是指將大型,笨拙的程式設計任務分解為單獨的,更小的,更易於管理的子任務或模組的過程。然後可以像構建塊一樣拼湊單個模組以建立更大的應用程式。

在大型應用程式中模組化程式碼有幾個優點:

  • 簡單性:模組通常只關注問題的一小部分,而不是關注當前的整個問題。如果您正在處理單個模組,那麼您的頭腦中要思考的將有一個較小的問題範圍。這使得開發更容易,更不容易出錯。

  • 可維護性:模組通常設計為能夠在不同的問題域之間實施邏輯邊界。如果以最小化相互依賴性的方式編寫模組,則對單個模組的修改將對程式的其他部分產生影響的可能性降低。(您甚至可以在不瞭解該模組之外的應用程式的情況下對模組進行更改。)這使得許多程式設計師團隊在大型應用程式上協同工作更加可行。

  • 可重用性:單個模組中定義的功能可以通過應用程式的其他部分輕鬆地重用。這消除了重新建立重複程式碼的需要。

  • 範圍:模組通常定義一個單獨的名稱空間,這有助於避免程式的不同區域中的變數名之間的衝突。

函式模組都是Python中用於促進程式碼模組化的構造。

一、模組分類

實現方式分類

實際上有兩種不同的方法可以在Python中定義模組

  1. 模組可以用Python本身編寫。
  2. 模組可以用C編寫並在執行時動態載入,就像re正規表示式)模組一樣。

以上兩種情況下,模組的內容都以相同的方式訪問:使用import語句

模組的歸屬分類

    1. 包含在解釋中的一個內建的模組本,像itertools模組
    1. 其他機構或個人開發者編寫的模組,成為第三方模組
    1. 自己寫的 .py 檔案,就是自定義的模組

第三方模組

從網路上下載的模組稱為 第三方模組

安裝方法

  1. pip3 工具安裝
    例如下面的示例是安裝用於執行遠端主機命令的模組 paramiko

注意: pip3 是 bash 環境下的命令

$ pip3 install paramiko

python2.x 使用 pip
python3.x 使用 pip3
當然這也不是固定的,比如你給 pip3 定義了一個別名 pip

  1. 原始碼安裝

原始碼安裝就是,從網路上下載沒有封裝的 python 檔案的原始碼,之後在本地執行其原始碼中的 setup.py 檔案進行安裝。

模組的原始碼一般都有一個主目錄,主目錄中包含了一個到多個子目錄和檔案。
但是主目錄下一定有一個 setup.py 的檔案,這個是原始碼安裝的入口檔案,就是需要執行這個檔案並且傳入一個 install 引數進行原始碼安裝。

示例:

a. 下載原始碼包

wget https://files.pythonhosted.org/packages/4a/1b/9b40393630954b54a4182ca65a9cf80b41803108fcae435ffd6af57af5ae/redis-3.0.1.tar.gz

b. 解壓原始碼包

tar -xf redis-3.0.1.tar.gz
  1. 進入模組原始碼的主目錄,並安裝原始碼包
11414906-9cbc97bbe66a6cb7.png
千鋒雲端計算楊哥團隊@shark
11414906-a626a091f7d0681c.png
千鋒雲端計算楊哥團隊@shark

上面表示安裝成功

自定義模組

有的情況下,是需要自己編寫一些模組的,這種就是自定義模組了。

示例:

some_mod.py

x = 10

li = ['shark', 18]

def foo():
    return 30

class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age

內建模組

模組除了 第三方模組, 自定義模組,還有 內建模組

模組的使用

使用模組需要先匯入模組名。

模組名就是把 .py 去掉後的檔名。比如 some_mod.py 的模組名就是 some_mod

a. 匯入模組

import  some_mod

b. 使用模組中的物件

要想使用模組中的變數名或者函式名等,只需要使用 模組名.變數名 的方式即可。

例如,下面是使用的了 some_mod 模組中的 foo 函式。

import  some_mod

some_mod.foo()

更多模組匯入的方式

a. 從模組中匯入其中的一個物件

from some_mod  import  x

b. 從模組中匯入多個物件

from some_mod import x, foo

c. 從模組中匯入全部的物件, 不建議這麼做

from some_mod import *

匯入模組時模組的程式碼會自動被執行一次

st = """www.qfecu.com
千峰歡迎您!
www.qfecu.com
千峰歡迎您!
"""

print(st)

二、包

包就是包含了一個 __init__.py 檔案的資料夾,這個資料夾下可以有更多的目錄或檔案。就是說,包裡可以用子包或單個 .py 的檔案。

其實包也是模組,就是說包和單一的 .py 檔案統稱為模組。

包的目錄結構

11414906-450e957071454a51.png
千鋒雲端計算楊哥團隊@shark

檔案 __init__.py

__init__.py 檔案,在 Python3.x 中可以沒有,但是在 Python2.x 中必須有。

檔案中可以有程式碼,也可以是個空檔案,但是檔名不能是其他的。

到匯入包的時候,此檔案假如存在,會以此檔案去見包的名稱空間。

也就是說,匯入如包的時候,只要在 __init__.py 檔案中的名稱才可以生效。否則,即使是一個模組在包目錄下面也不會被匯入到記憶體中,也就不會生效。

使用包

示例包目錄機構

11414906-8882408b73263987.png
千鋒雲端計算楊哥團隊@shark

使用包也需要匯入

a. 單獨匯入包

import package  # 注意這樣不會匯入其下面的模組和子包

b. 從包中匯入下面的模組

from package import t

c. 從包中匯入下面的子包,注意這不會匯入子包下面的任何模組

from package import subpkg

d. 從包的子包中匯入子包的模組

from package.subpkg import som_mod

e. 從包或子包的模組中匯入具體的物件

from package.t  import foo

from package.subpkg.som_mod import x

from package.t  import x  as y   # 把 x 匯入後起個別名 y

記住一點:不論是匯入包還是模組,從左向右的順序來說,最後一個點兒的左邊一定是一個包名,而不能是一個模組名

下面是錯誤的

import package.t.foo
from package.subpkg import som_mod.x

三模組的內建變數 __name__

每個 .py 檔案都有一個變數名 __name__, 這個變數名的值會根據這個檔案的用途不同而隨之變化。

  1. 當檔案作為模組被其他檔案使用時,__name__ 的值是這個檔案的模組名

  2. 當檔案作為指令碼(就是作為可執行檔案)使用時,__name__ 的值是字串型別的 '__main__'

通常你會看到一些 Python 指令碼中會有類似下面的程式碼:

some_script.py

def foo():
    pass

def func():
    pass

def main():
    foo()
    func()

if __name__ == '__main__':
       main()

使用這個指令碼

python3 some_script.py

這樣執行這個指令碼的話,其內建的 __name__ 變數的值就是字串的 '__main__'
這樣的話, if 的判斷新增就會達成,從而其語句下面的程式碼就會執行, main() 函式就會被呼叫 。

模組名的搜尋路徑

當你匯入模組或者包的時候, 查詢模組或包的順序:

  1. 系統會先從當前目錄下查詢

  2. 之後再從sys.path 輸出的值中的路徑裡查詢模組名或者包名。

import sys

print(sys.path)

sys.path 輸出的值是一個 Python 的列表,這個列表我們可以對其修改的。

比如我們可以把某個檔案的路徑新增到此列表中,通常會這麼做。

run.py

import os,sys

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

sys.path.insert(0, BASE_DIR)

相關文章