---
# System prepended metadata

title: Module(模組)/Package(套件)
tags: [Python]

---

# Module(模組)/Package(套件)

###### tags: `Python`

## 前言
>在開發程式的過程中，程式碼會愈寫愈多，規模也會愈來愈大，這時候如果都把所有程式碼放在同一個檔案裏頭會變得難以維護跟管理，所以適時的拆解程式碼，並把**相關性高的程式碼分門別類丟進不同的檔案中，就能方便主程式呼叫，提高重用性**。常見的方法有**模組**跟**套件**。

<!--more-->

## Module(模組)
>**將相關性較高的程式碼抽出來放在不同的檔案內，而每個檔案就是模組。** 由主程式去呼叫模組的程式碼就可以提高重用性。

舉一個銀行帳戶的例子來說，現在有兩個模組 `info.py`, `spending.py`:

`info.py` 模組
```
# 取得帳戶名稱
def get_name():
    return MaDi
    
# 取得存款
def get_deposit():
    return 50000
```
`spending.py` 模組
```
def earn(money):
    ...
    
def spend(money):
    ...
```


載入模組的方法:
1. `import 模組.py`: 整個模組載入，如果要用內部的函式或類別則要由模組名稱去呼叫，ex: `info.get_name()`
2. `from 模組 import 函式/類別`: 只載入模組中的特定物件，可以直接使用模組內的函式或類別，ex: `get_name()`

在C、C#編譯語言裏頭，常常稱這種方式為另一個名稱`library`，如動態庫檔名為`xxx.dll`，兩者都是提供功能給使用者呼叫，但在python中常以模組稱之。

## Package(套件)
>當模組數量變多的時候，就要準備一個容器去裝他們。而這裡的容器就是資料夾，**當一個資料夾中包含一個或多個模組，並擁有`__init__.py`來撰寫初始化的程式碼，這個資料夾就是套件。** 原則一樣是把相似的模組組織成套件，以利維護與重用性。

舉例來說，

```
account/            # 套件名稱
    __init__.py     # 內容可為空，但一定要有此檔
    info.py         # 模組1
    spending.py     # 模組2
    subpackage/     # 套件中也可以有子套件
        module3.py  # 子套件中再有模組
```

從套件中載入模組的方法:
1. `import 套件.模組`:  ex: `import account.info`
2. `from 套件 import 模組`: ex: `from account import info `

**`__init__.py`可以不用撰寫任何程式碼，但一定要在資料夾內才能使該資料夾變為套件。**

### dir()
>dir(模組名稱)
>
python內建的函式，可以**查看模組內有哪些屬性(Attributes)與方法(Method)**。

其中，最特殊的是`__name__`，代表該模組的名稱，可以用來區分程式目前執行的角色。

舉例來說，在 `info.py`的模組中加上`print(__name__)`到最後一行
```
# 取得帳戶名稱
def get_name():
    return MaDi
    
# 取得存款
def get_deposit():
    return 50000

# 模組名稱
print(__name__)
```
如果直接執行`info.py`，`__name__` 會回傳 `__main__`，但如果是從主程式去呼叫`info.py`，則`__name__` 會回傳 `account.info`。

也就是說，當程式執行的角色不同，模組的名稱也會改變，**直接運行程式碼則模組名稱為`__main__`。**

所以我們可以透過以下方式去區分**模組是自己直接被執行or被主程式呼叫**:
```
# 載入模組要做的事...

if __name__ == "__main__":
    # 直接執行摸組要做的事...
```



## 參考
* [解析Python模組(Module)和套件(Package)的概念](https://www.learncodewithmike.com/2020/01/python-module-and-package.html)
* [python day17 (module、package)](https://ithelp.ithome.com.tw/articles/10223780)
* [Python的包裝機制 — Function, Class, Module, Package](https://medium.com/%E5%AE%85%E7%94%B7%E9%9B%9C%E5%AD%B8%E7%AD%86%E8%A8%98/python%E7%9A%84%E5%8C%85%E8%A3%9D%E6%A9%9F%E5%88%B6-function-class-module-package-29bd8defb20e)
* [簡易理解python中的if __name__ == 'main' 的作用和原理](http://hn28082251.blogspot.com/2019/05/python-if-name-main.html)