目次
1. 簡介
Python 是一種以簡單且易讀的語法為特色的程式語言,從初學者到專業人士都有廣泛的使用。在其中,「變數的初始化」是學習 Python 時初學者最先面對的重要概念之一。 變數是指在程式中暫時儲存資料的「具名容器」。而初始化則是指為這個容器設定初始值的作業。在 Python 中,不像 C 語言或 Java 那樣需要明確指定型別,但如果不進行適當的初始化,可能會導致錯誤、程式碼的可讀性或維護性受損。 例如,「原本想將列表空初始化,但卻在跨函數時值被共享了」「用 None 初始化了,但意圖不明確導致了 bug」等問題,往往是因為對初始化的理解不足所致。 本篇文章將系統性地說明 Python 中變數的初始化方法。從基本的數值和字串初始化,到列表、字典等複雜資料型別,甚至函數和類別中的初始化注意事項,都會以初學者也能輕鬆理解的方式詳細介紹。 對於以「Python 變數 初始化」為關鍵字搜尋的使用者,本文充滿了對實務或學習有幫助的具體資訊,請務必閱讀至最後。2. Python 中的變數初始化是什麼?
變數的初始化是什麼?
「變數的初始化」是指在程式中使用變數之前,先賦予其初始值的行為。換句話說,這是告訴程式「這個變數是用來做這種用途的」最初步驟。 例如,以下程式碼將變數count
初始化為整數 0。count = 0
這樣做可以讓使用變數 count
的計算或比較處理更順暢。Python 中的初始化特點
Python 被稱為「動態型別語言」,宣告變數時不需要明確指定型別。例如,整數或字串,都可以像這樣直接使用。number = 100 # 初始化為整數
text = "Hello" # 初始化為字串
C 語言或 Java 中,需要先明確指定型別後才能宣告和初始化變數,但 Python 沒有這種麻煩,因此可以直覺地撰寫程式碼。 不過,這種彈性有時會適得其反,例如意外放入不預期的資料型別,或不小心使用未初始化的變數導致錯誤。使用未初始化的變數會怎麼樣?
在 Python 中,試圖存取未初始化的變數時,會發生NameError
錯誤。以下是其中一例。print(user_name)
像上面這樣,在尚未為 user_name
賦值的情況下存取,就會發生下列錯誤。NameError: name 'user_name' is not defined
為了避免這種錯誤,在使用變數前務必先初始化。隱式初始化與顯式初始化
在 Python 中,通常是「隱式初始化」,也就是想用時直接賦值就完成了初始化。不過,為了撰寫更安全且明確的程式碼,有時建議事先使用None
或空清單等進行「顯式初始化」。 例如:data = None # 值尚未確定,但明確表示未來將使用
這樣做,可以事先宣告變數的存在,讓團隊開發或日後閱讀時更容易理解。3. 基本初始化方法與資料型別的範例
在 Python 中,變數的初始化非常簡單,只要賦值即可完成。在這裡,我們將介紹常用基本資料型別的初始化方法,並附上具體的程式碼範例。3.1 數值・字串的初始化
在 Python 中初始化數值(整數・浮動小數點)或字串,只要像下面這樣賦值即可。count = 0 # 整數的初始化
temperature = 36.5 # 浮動小數點的初始化
message = "你好" # 字串的初始化
這些初始化特別不容易發生錯誤,而且直觀易用。數值和字串是 Python 的基本中的基本,所以要能順利處理才行。3.2 使用 None 的初始化
當還沒有決定值,或者想要明確表示「為空」時,None
很方便。username = None
這樣初始化後,就能「這個變數之後會被賦予某個值,但目前尚未決定」在程式碼上顯示出來。 None
類似於 null
的概念,當函數沒有返回值時等,也會被返回。經常與條件分歧結合使用。if username is None:
print("使用者名稱尚未設定")
3.3 列表・字典・集合等的初始化
處理多個值時,使用列表、字典、集合(set)。以下是初始化方式。my_list = [] # 空的列表
my_dict = {} # 空的字典
my_set = set() # 空的集合(※ {} 會變成字典,所以注意)
各自用途不同,所以要在適當的場合區分使用。- 列表(list):有順序的資料集合
- 字典(dict):由鍵值對構成的資料結構
- 集合(set):想要保持無重複資料時使用
3.4 元組的初始化
元組是一旦建立就無法變更的「不變資料集合」。初始化範例如下。empty_tuple = () # 空的元組
point = (10, 20) # 像座標的固定配對
因為不變性得到保證,所以想要將多個值作為「固定集合」處理時很方便。 注意點是,單一元素的元組需要像 (value,)
這樣加上逗號。single = (5,) # 這樣就成為單一元素的元組
總結:依用途進行適當的初始化
依資料種類進行適當的初始化,能夠避免錯誤並提升程式碼的可讀性。特別是列表或字典等複雜的資料結構,在與後述的函數或類別組合時會有注意點,所以在基礎階段要好好理解才行。
4. 常見的注意事項與錯誤
Python 的變數初始化看起來很簡單,但實際上對於初學者來說,有幾個容易絆倒的點。在這裡,我們將特別說明容易被忽略、容易導致實際 bug 或意外行為的「初始化陷阱」。4.1 注意可變的預設引數
在 Python 中定義函數時,使用列表或字典作為預設引數,可能會發生意想不到的行為。 以下的程式碼,看起來似乎沒有問題。def add_item(item, items=[]):
items.append(item)
return items
然而,當多次呼叫這個函數時,會發生前一次的結果被繼承的現象。print(add_item("A")) # ['A']
print(add_item("B")) # ['A', 'B'] ← 意圖外的行為
這個問題是因為在函數定義時 items=[]
只被評估一次,並被重複使用。正確的寫法
在這種情況下,使用None
來初始化,並在函數內建立列表是最安全的。def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
4.2 變數範圍與初始化的混亂
在 Python 中,全域變數與區域變數即使名稱相同,也會根據範圍被視為不同的東西。 在以下的範例中,看起來像是使用相同的counter
,但由於範圍不同,因此被視為不同的變數。counter = 10
def increment():
counter = counter + 1 # 會發生錯誤
print(counter)
這個程式碼在執行時會產生 UnboundLocalError
。原因是,在函數內試圖對 counter
賦值,因此 Python 將其視為「區域變數」。但是,該區域變數尚未初始化,因此發生錯誤。正確運行的方法
- 如果要在函數內變更值,請使用
global
關鍵字 - 或者,設計成透過引數或回傳值來傳遞值
def increment():
global counter
counter += 1
print(counter)
4.3 不注意型別的初始化陷阱
Python 是動態型別語言,因此型別會自動變更。這一方面很方便,但也可能成為 bug 的原因。value = 5 # 整數
value = "5" # 這次是字串
這樣的程式碼看起來會正常運作,但之後如果試圖將 value
當作數值來處理,就會發生錯誤。result = value + 1 # TypeError: can only concatenate str (not "int") to str
對策
- 如果想固定型別,請使用型別註解(後述)
- 至少,在變數初始化時明確「這個變數是用來存放什麼的」
小結:了解注意事項可以防止 bug
Python 雖然是對初學者友善的語言,但「易懂性」的背後也隱藏著陷阱。特別是,可變物件的處理、範圍的差異、型別的曖昧性,即使在實務層級也容易成為 bug 的原因。 為了避免此類問題,不僅要掌握初始化的基本知識,事先了解容易發生的錯誤及其對策也很重要。5. 函數或類別中的初始化最佳實務
函數中的變數初始化
區域變數的初始化
Python 的函數內定義的變數,會被視為該函數的區域變數。它們獨立於函數外部,如果嘗試使用未初始化的變數,會發生錯誤。def greet():
message = "你好"
print(message)
greet()
因此,使用函數內變數時,務必在函數內初始化 非常重要。安全預設引數的使用方式
如前章所述,如果在預設引數中使用可變物件(清單或字典),可能會發生意外的值共享。 安全初始化的方法,建議使用None
,並在函數內進行初始化。def append_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
這種風格具有高再利用性,能帶來安全且可預測的函數設計。類別中的變數初始化(__init__
方法)
在 Python 的類別中,生成實例時會呼叫 __init__
方法。在此處進行實例變數的初始化。實例變數的初始化
class User:
def __init__(self, name):
self.name = name
self.age = None # 之後預定賦值的變數也在这里初始化
user1 = User("Sato")
print(user1.name) # → Sato
透過附加 self.
進行初始化,即可讓每個實例擁有獨有的資料。注意類別變數的差異
Python 具有實例變數和類別變數。若不理解差異就使用,可能會發生意外的資料共享。class Sample:
shared_list = [] # 類別變數(全實例共享)
def __init__(self):
self.my_list = [] # 實例變數(各實例獨立)
a = Sample()
b = Sample()
a.shared_list.append("A")
b.shared_list.append("B")
print(a.shared_list) # → ['A', 'B']
print(b.shared_list) # → ['A', 'B']
類別變數會被全實例共享,因此不適合用於持有狀態。如果需要每個狀態獨立的資料,務必使用 self.
在 __init__
中初始化。透過初始化明確化程式碼意圖
函數或類別中的變數初始化,也是明確「此變數預定如何使用」的設計要素。適當初始化,能讓後續閱讀程式碼的人(或未來的自己)更容易理解。6. 活用型提示進行初始化(Optional, Union)
什麼是型提示?
型提示是,在變數或函數的引數・返回值中明確指定「預計使用此型別」的機制。從 Python 3.5 開始標準支援,並可從靜態分析工具(mypy 或 Pyright)或編輯器(VS Code、PyCharm 等)獲得補全・警告的益處。name: str = "Yamada"
age: int = 25
is_active: bool = True
如上所述,在變數名後面加上冒號(:)和型別名稱,即可明確指定型別。使用 Optional 進行初始化
Optional
是用來表示「某變數可能為某型別或 None」的型提示。例如,對於「尚未設定,但之後可能會放入字串」的變數,可以如下使用。from typing import Optional
username: Optional[str] = None
這與以下相同:from typing import Union
username: Union[str, None] = None
也就是說,Optional[X]
是 Union[X, None]
的簡寫表示。 如此寫法,可以明確表示「此變數可能處於未設定狀態(None),但預期最終會成為 str」的意圖。使用 Union 允許多個型別
使用Union
,即可進行「此變數可採用多個型別之一」的彈性定義。from typing import Union
data: Union[int, str] = 42
data = "文本" # 兩者皆 OK
這在維持動態型別檢查的優點的同時,限制型別的選項,防止未預期的錯誤的目的下使用。帶型提示的列表或字典初始化
列表或字典也可以用型提示詳細指定。from typing import List, Dict
names: List[str] = []
user_ages: Dict[str, int] = {}
如上所述寫法,可以明確傳達「此列表僅放入字串」「此字典放入字串鍵和整數值」的規格。型提示的效果與活用優點
- 編輯器補全強化:候選縮減,因此打字錯誤減少
- 有助於早期發現錯誤:可用 mypy 等事先偵測不一致
- 可取代文件:即使是他人程式碼,也更容易理解用法
總結:明確初始化,讓程式碼易讀且安全
Python 是對型別不嚴格的語言,但活用型提示可大幅提升程式碼的可靠性。在初始化時使用 Optional 或 Union 明確表示意圖,即可更容易防止錯誤,並使未來的維護更輕鬆。7. 常見問題(FAQ)
這裡,我們以「Python 變數 初始化」相關的問題,彙整了初學者常見的疑問,以問答形式呈現。每個回答中,也會一併介紹實用的程式碼範例及注意事項。Q1. Python 中變數不指定型別會有問題嗎?
A1. 即使不指定型別也能運作,但使用型別提示會更安全。 Python 是動態型別語言,因此只需像這樣寫,就能使用變數。age = 25 # 無型別指定(int)
name = "Satō" # 無型別指定(str)
不過,如果之後賦值不同的型別,可能會導致意想不到的錯誤。因此,為了提升程式碼的可讀性、自動補全支援及型別檢查,建議使用型別提示(type hints)。age: int = 25
Q2. 為什麼要用 None
初始化變數?
A2. 為了明確表示「值尚未存在」。 在 Python 中,使用 None
可以清楚地表示「尚未設定值」的狀態。result = None # 預期之後會賦值
特別適合用於函數的返回值、可選引數,或狀態尚未確定的變數初始化。此外,使用 None
可以像 if result is None:
這樣簡潔地判斷狀態。Q3. 清單的正確初始化方法是什麼?
A3. 空清單用[]
初始化,但函數引數需注意。items = [] # 一般的初始化這樣即可
不過,如果在函數的預設引數中使用 []
,值會被共享,有危險。def add(item, items=[]): # ❌ 每次執行值會累積
items.append(item)
return items
正確的做法是使用 None
在函數內初始化。def add(item, items=None): # ✅
if items is None:
items = []
items.append(item)
return items
Q4. 類別的變數與其他實例共享值了,為什麼?
A4. 需要理解類別變數與實例變數的差異。 Python 的類別有以下兩種變數:- 類別變數:整個類別共享
- 實例變數:每個實例獨立的值
class Sample:
shared_list = [] # 類別變數(全實例共享)
def __init__(self):
self.my_list = [] # 實例變數(各實例獨立)
a = Sample()
b = Sample()
a.shared_list.append("A")
b.shared_list.append("B")
print(a.shared_list) # → ['A', 'B']
print(b.shared_list) # → ['A', 'B']
為了避免意外共享,請使用實例變數 self.變數名
,並在 __init__
內初始化。Q5. 變數初始值使用 0
或 ""
與 None
的區別該如何?
A5. 根據值是「未定」還是確定為「空」來區分使用。狀態 | 初始值的範例 | 含意 |
---|---|---|
未設定・未定 | None | 值尚未決定 |
確定為空 | 0 , "" , [] | 明確知道是「空」 |
None
,如果預設使用空清單則用 []
。透過明確區分意圖,可以提升後續處理的安全性與可讀性。8. 總結|Python 初始化最佳實務
這篇文章中,我們從基礎到實務應用、常見錯誤以及型別提示的使用方法,廣泛地說明了「Python 的變數初始化」。 Python 是一種動態型別的靈活語言,但相對地,「初始化的模糊性」容易導致意外的錯誤或 bug 也是其特點之一。因此,養成以下的 初始化最佳實務,將直接連結到健康的程式碼撰寫。✅ 初始化最佳實務總結
- 基本型別(int、str、list 等)要明確地初始化
count = 0
name = ""
items = []
- 想要明確未定義狀態時,使用
None
result = None
- 函式的預設引數不要使用可變型別(列表・字典等)
def func(data=None):
if data is None:
data = []
- 類別中要為每個實例以
self.變數名
進行初始化
class User:
def __init__(self, name):
self.name = name
- 使用型別提示(Optional, Union)來明確程式碼的意圖
from typing import Optional
age: Optional[int] = None
✍️ 給初學者的建議
在 Python 中,程式碼「能運作」與「安全・明確」是兩回事。一開始注重能運作並沒有問題,但逐步學習明確的初始化意圖和型別的使用方式,就能撰寫出 bug 較少、可靠度高的程式碼。📘 相關主題(為了進階)
- Python 的作用域和命名空間的理解
- 使用
mypy
等進行型別檢查的自動化 - 資料類別(
@dataclass
)來簡化初始化 - 與 IDE(VS Code、PyCharm)聯動來活用型別補全