# Python import module 和 from module import * 的差別?
:::info
🚀 **30秒重點統整:**
1. **存取方式差異**
- `import module` → 使用 `module.function()` 存取模組內功能
- `from module import *` → 可直接使用 `function()`,但來源不明確
2. **命名空間影響**
- 前者保持模組獨立命名空間,避免命名衝突
- 後者將所有內容導入當前命名空間,可能覆蓋同名變數或函式
3. **實務建議**
- **大型專案**:用 `import module` (清晰、安全)
- **特定需求**:用 `from module import func` (只匯入需要的功能)
- **避免使用** `from module import *` (除非快速測試腳本)
📌 **經典錯誤範例:**
```python=
from math import sqrt
sqrt = 3.14 # 原來的 sqrt() 函式被新數值覆蓋
print(sqrt(16)) # 導致 TypeError: 'float' object is not callable
```
:::
在 Python 中,`import module` 和 `from module import *` 是兩種不同的模組匯入方式,它們的差異主要體現在作用域、程式碼可讀性和命名衝突風險上。
### 1. `import module`
這種匯入方式會將整個模組匯入到目前的命名空間中,但模組內的函式、類別和變數都需要透過模組名稱前綴來存取。例如:
```python=
import math
print(math.sqrt(16)) # 使用模組名稱作為前綴
```
#### 特點:
- **作用域清楚**:所有的函式和變數都屬於 `module`,避免命名衝突。
- **程式碼可讀性高**:透過模組名稱前綴,可以清楚地知道某個函式或變數來自哪個模組。
- **適合大型專案**:尤其是當多個模組中存在相同名稱的函式或變數時,使用這種方式可以避免混淆。
---
### 2. `from module import *`
這種匯入方式會將模組中的所有函式、類別和變數直接匯入到目前的命名空間中,因此可以直接使用它們,而不需要模組名稱前綴。例如:
```python=
from math import *
print(sqrt(16)) # 不需要模組名稱前綴
```
#### 特點:
- **簡化程式碼**:可以直接使用模組中的函式或變數,程式碼更簡潔。
- **容易引發命名衝突**:如果目前的作用域中已經有相同名稱的函式或變數,會覆蓋原來的定義。例如:
```python=
from math import *
def sqrt(x):
return x # 自訂的函式會覆蓋 math模組的sqrt
print(sqrt(16)) # 輸出 16,而不是 4
```
- **不建議使用**:由於難以追蹤變數或函式的來源,這種方式不利於程式碼的可讀性與維護。
📌 **經典錯誤範例:**
```python=
from math import sqrt
sqrt = 3.14 # 原來的 sqrt() 函式被新數值覆蓋
print(sqrt(16)) # 導致 TypeError: 'float' object is not callable
```
:::spoiler **經典錯誤範例解析**:
#### 💥 **發生什麼事?**
1. **匯入 `sqrt` 函式**:
- `from math import sqrt` 把 `math.sqrt` 函式匯入到當前命名空間。
- 這時,`sqrt` 是一個函式,用於計算平方根。
2. **重新定義 `sqrt`**:
- 後續程式直接賦值:`sqrt = 3.14`。
- 此操作覆蓋了之前的 `sqrt` 函式,現在 `sqrt` 是一個浮點數變數 (值為 3.14)。
3. **函式調用錯誤**:
- `print(sqrt(16))` 試圖將 `sqrt` 當作函式調用,但此時 `sqrt` 是數值類型(浮點數)。
- 結果觸發錯誤:
```plaintext
TypeError: 'float' object is not callable
```
#### 🔥 **為什麼會發生這樣的錯誤?**
- 使用 `from module import *` 或直接匯入單一函式時,匯入的內容會直接進入當前命名空間。
- 當前命名空間的任何變數或函式,如果名稱與匯入內容重複,會覆蓋匯入的內容。
- 這種情況容易發生,特別是在命名不嚴謹的情況下。
#### ⭐️ **正確的作法:**
```python=
import math # 或 from math import sqrt as math_sqrt
sqrt = 3.14 # 不會影響 math.sqrt()
print(math.sqrt(16)) # 安全地調用平方根函數,輸出 4.0
```
:::
---
### 總結
- **使用情境**:
- 若想避免命名衝突並維持程式碼的清晰性,建議使用 `import module`。
- 如果只需要模組中的部分功能,可以使用 `from module import specific_function`,例如:
```python=
from math import sqrt, pi
print(sqrt(16))
print(pi)
```
- 不建議使用 `from module import *`,除非在互動式環境或快速測試腳本中使用,且確保不會引發命名衝突。