Python 101 基礎教學 (9) - 模組 module 與套件 package

寫程式從來就是站在巨人的肩膀上。Python 提供了許多的內建模組便利我們加速開發,事半功倍。除此之外你可以用第三方的函式庫,你也可以自己造輪子,寫自己的套件模組。

Import

我們可以利用 import 這個關鍵字來載入我們要用的模組。舉例來說,我們可以使用 random 模組寫一個會隨機回傳數字1 ~ 10的函式:

import random

def get_rand():
    return random.randint(1, 10)

print(get_rand()) # 隨機印出1 ~ 10

random 是一個 python 的內建模組,以上例子使用了 randint 這個屬於 random 的方法來隨機產生一個 1 ~ 10 的數字。你可以使用 random.xxx 來使用此模組的各種方法, randint 只是其中一種。你也可以用 "from" 來明確指出要載入的方法:

from random import randint # 你指定只載入randint這個方法

def get_rand():
    return randint(1, 10) # 這裡可以直接使用已載入的randint

print(get_rand()) # 隨機印出1 ~ 10

某些情況下方法名太長或是兩個模組有衝突,你可以使用 "as" 去更改它的名字:

from random import randint as ri # 把randint命名成ri

def get_rand():
    return ri(1, 10) # 這裡可以直接使用已載入的randint(ri)

print(get_rand()) # 隨機印出1 ~ 10
import random as rd # 把random命名成rd

def get_rand():
    return rd.randint(1, 10)

print(get_rand()) # 隨機印出1 ~ 10

使用第三方模組

除了內建的模組外,秉持著站在巨人肩膀上辦事的原則,用第三方的模組也是不可避免的。如果你是學data相關的工程師,numpy、pandas等都算是第三方模組,在使用之前必須先安裝。

安裝方式有很多種,通常要用的模組指引裡面都會告訴你安裝方法,最常見的有利用 Anaconda 、或是用指令 pip 安裝(ex. pip install numpy

使用 import 時,如果找不到模組的時候,會報 ModuleNotFoundError 錯誤。假如你在載入第三方模組遇到此錯誤的話,檢查一下,可能是你的模組在安裝過程中出了問題。

寫自己的套件 package / 模組 module

package/
    __init__.py
    module1.py
    module2.py
    subpackage/
        module3.py

package 其實就是用來組織 modules 的,我們可以用檔案與目錄來想像 module 與 package。package 裡也可以有 subpackage。

當你 import package 時,__init__.py 的內容會自動被執行。在python3.3 以前的版本,寫 package 是強制需要 __init__.py 這隻檔案的,所以我們常會看到很多空的__init__.py。新的版本如果你沒有要在 import 時做事情,那就不需要這隻檔案。

以下為一個簡單的例子

main.py
calc/
    add.py
    substract.py
我們create一個python的project,檔案結構如這個
def add1(x):
  return x + 1

def add(x, y):
  return x + y
calc/add.py
def sub1(x):
  return x - 1

def sub(x, y):
  return x - y
calc/substract.py
from calc import add
from calc import substract as sub

a = add.add1(5)
print(a) # output: 6
b = add.add(1, 3)
print(b) # output: 4

c = sub.sub1(5)
print(c) # output: 4
d = sub.sub(4, 1)
print(d) # output: 3
main.py

import 的方式有很多種,也有分絕對路徑 Absolute Imports 相對路徑 Relative Imports的差別。

# 用*可以把模組裡的所有方法都一次import,但不推薦,容易造成混亂。
from calc.add import *

a = add1(5)
print(a) # output: 6
b = add(1, 3)
print(b) # output: 4
# 以下是需要用到的時候再import,推薦!
from calc.add import add1
from calc.add import add

a = add1(5)
print(a) # output: 6
b = add(1, 3)
print(b) # output: 4
# 也work,但prefer使用"from"
import calc.add as add

a = add.add1(5)
print(a) # output: 6
b = add.add(1, 3)
print(b) # output: 4

要使用相對路徑的話在 module 或是 package 前面加一個點"."表示當前目錄,".."代表上一層,以此類推。

# 假設今天想再 substract.py 裡加一個新的函式叫做 sub_add_add1,
# 可以先把兩數相減再加上一,然後我們想使用 add.py裡的 add1。
# 因爲 add.py 與 substract.py 在同一個pacakge下,我們可以用相對路徑的方式載入:
from .add import add1

def sub1(x):
  return x - 1

def sub(x, y):
  return x - y
  
def sub_and_add1(x, y):
  return add1(x - y)
calc/substract.py

參考:https://docs.python.org/3/reference/import.html#regular-packages

繼續閱讀:

Python 101 基礎教學 (10) - 物件導向 Object-Oriented Programming
物件導向 Object-Oriented Programming(OOP) 是以物件的形式去描述你資料應有的行為。就像我們在現實世界中定義貓、狗、人、車等等一樣,都有自己的運作方式。程式語言中我們也可以把資料想成物件,用物件導向去定義你的每個物件該如何運作。