本文 AI 產出,尚未審核

Python 基本語法 ── 識別字與命名慣例(snake_case)

簡介

在任何程式語言中,識別字(identifier) 都是程式的「名片」:變數、函式、類別、模組等都需要透過有意義且可辨識的名稱來存取。若名稱隨意、難以閱讀,程式碼的可維護性、可讀性就會大幅下降。

Python 社群長期以來推崇 PEP 8(Python 程式風格指南)作為統一的編碼標準,其中最常見的命名慣例就是 snake_case——所有字母小寫,單字之間以底線(_)分隔。熟練掌握 snake_case 不僅能讓你的程式碼看起來「像 Python」;更重要的是,它能降低團隊合作時的溝通成本,讓程式碼審查、除錯變得更順暢。

本篇文章將從 識別字的語法規則snake_case 的具體寫法實務範例常見陷阱與最佳實踐,一步步帶你建立正確的命名觀念,無論是剛踏入程式世界的新人,或是已經有幾年開發經驗的中階工程師,都能從中獲得實用的技巧與啟發。


核心概念

1. 識別字的基本語法

規則 說明
必須以 字母 (A‑Z, a‑z) 或底線 (_) 開頭 數字只能出現在開頭之後,例如 var1 合法、1var 不合法。
後續字元可以是 字母、數字或底線 my_var2, _temp, data_2023 都是合法的識別字。
大小寫敏感 valueValue 被視為不同的變數。
不能使用 Python 關鍵字(如 for, class, def)作為名稱 若一定要使用,可在名稱後加底線,例如 class_
Unicode 允許使用 非 ASCII 字元(如中文、日文) 雖然語法允許,但不建議在程式碼中使用,以免跨平台相容性問題。

小技巧:在 Python REPL 中,使用 keyword.iskeyword('for') 可以快速檢查字串是否為關鍵字。

2. 為什麼使用 snake_case?

  1. 可讀性:底線明確分隔單字,閱讀時自然斷句。
  2. 符合 PEP 8:Python 官方風格指南明確規定,遵循可避免 lint 工具的警告。
  3. 跨平台一致性:不同作業系統的檔案系統對大小寫敏感度不同,統一使用小寫能減少意外。
  4. 團隊協作:統一的命名慣例讓新加入的成員快速上手,減少溝通成本。

注意:類別名稱則使用 PascalCase(首字母大寫),例如 MyClass;常數則使用 UPPER_SNAKE_CASE,例如 MAX_CONNECTIONS。本篇聚焦於變數與函式的 snake_case。

3. snake_case 的寫法原則

原則 範例 說明
全小寫 user_name 絕不使用大寫字母。
單字以底線分隔 total_price 多個單字時,用 _ 連接。
避免連續底線 http_response (✔) vs http__response (✘) 連續底線會降低可讀性,且易與「私有變數」__private 混淆。
不要以底線結尾 file_path (✔) vs file_path_ (✘) 結尾底線常被誤用於保留字或特殊情況。
盡量使用具體語意 max_retry_attempts (✔) vs x (✘) 具體名稱能讓程式碼自說自話。

程式碼範例

以下示範 5 個常見情境,從變數宣告、函式命名到模組匯入,皆採用 snake_case。

# 範例 1:變數命名
user_id = 12345                     # 使用底線分隔單字
total_price = 199.99                # 數值型變數
is_active = True                    # 布林值以 is_ / has_ 開頭較易閱讀

# 範例 2:函式命名
def calculate_discount(price: float, rate: float = 0.1) -> float:
    """
    計算折扣後的價格。
    :param price: 原始價格
    :param rate: 折扣率,預設 10%
    :return: 折扣後的金額
    """
    discounted_price = price * (1 - rate)
    return round(discounted_price, 2)

# 呼叫函式
final_price = calculate_discount(total_price)
print(f"折扣後金額:{final_price}")

# 範例 3:類別方法與私有屬性 (仍使用 snake_case)
class OrderProcessor:
    def __init__(self, order_id: int):
        self.order_id = order_id
        self._is_processed = False      # 單底線表示「受保護」屬性

    def process_order(self) -> None:
        """執行訂單處理流程"""
        if not self._is_processed:
            # ... 省略實作細節 ...
            self._is_processed = True
            print(f"訂單 {self.order_id} 已處理。")

# 使用類別
processor = OrderProcessor(user_id)
processor.process_order()

# 範例 4:模組匯入與別名
import datetime as dt               # 使用簡短且易讀的別名
current_time = dt.datetime.now()
print(f"現在時間:{current_time}")

# 範例 5:常數命名(仍遵循 snake_case 的變形)
MAX_RETRY_ATTEMPTS = 5               # 常數採用全大寫

重點說明

  • 變數、函式皆使用 全小寫 + 底線
  • 私有或受保護屬性以單底線開頭,避免與「魔術方法」__init__ 混淆。
  • 模組別名亦採用小寫,保持一致性。

常見陷阱與最佳實踐

陷阱 說明 解決方案
使用大寫字母 UserNameTotalPrice 看起來像類別名稱,易造成混淆。 嚴格遵守 全小寫 原則,若需要類別則改用 PascalCase。
連續底線 http__response__private_var(非魔術方法)會讓程式碼難以閱讀。 只在特殊情況(如 __init____str__)使用雙底線;一般變數避免。
與關鍵字衝突 class = 5 會直接產生 SyntaxError。 使用底線後綴(class_)或重新命名。
過長或過短 x, y 雖簡短,但意義不明;this_is_a_very_long_variable_name_exceeding_reasonable_length 讀起來也吃力。 適中長度,兼具語意與可讀性,例如 user_ageorder_total
不一致的命名 同一模組內部有 userNameuser_name 兩種寫法。 設定團隊 lint 規則(如 flake8pylint)自動檢查。

最佳實踐清單

  1. 統一風格:在專案根目錄加入 .flake8pyproject.toml,啟用 pep8-naming 插件自動偵測違規。
  2. 語意化:變數名稱應描述其用途,如 file_path 而非 fp,除非在局部範圍極短。
  3. 避免縮寫:除非是業界公認的縮寫(如 id, url),否則盡量寫全。
  4. 使用類別與函式的動詞:函式名稱以動詞開頭,如 fetch_datasave_to_file,讓呼叫意圖一目了然。
  5. 保持一致的底線數量:單底線分隔單字,雙底線僅保留給魔術方法或特殊用途。

實際應用場景

1. 資料分析腳本

在資料科學專案中,常會寫大量的 資料清理特徵工程 程式。以下是一段典型的 Pandas 操作,全部使用 snake_case:

import pandas as pd

def load_sales_data(csv_path: str) -> pd.DataFrame:
    """讀取銷售資料 CSV,並將日期欄位轉為 datetime」"""
    df = pd.read_csv(csv_path, parse_dates=['sale_date'])
    return df

def clean_sales_data(df: pd.DataFrame) -> pd.DataFrame:
    """資料清理:去除缺失值、過濾負數金額"""
    df = df.dropna(subset=['sale_amount'])
    df = df[df['sale_amount'] >= 0]
    return df

sales_df = load_sales_data('data/sales_2023.csv')
sales_df = clean_sales_data(sales_df)
print(sales_df.head())
  • load_sales_dataclean_sales_data 皆以 動詞 + 名詞 命名,清楚表達功能。
  • 變數 sales_dfcsv_path 皆遵循 snake_case,讓腳本在多人協作時不會產生命名衝突。

2. Web API 後端開發

在 Flask 或 FastAPI 等框架中,路由函式的名稱同樣使用 snake_case,配合路由字串的 kebab-case(如 /user-profile)形成一致的命名層次:

from fastapi import FastAPI, HTTPException

app = FastAPI()

users_db = {}

def get_user_by_id(user_id: int) -> dict:
    """根據 user_id 取得使用者資料"""
    return users_db.get(user_id)

@app.get("/users/{user_id}")
def read_user(user_id: int):
    user = get_user_by_id(user_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user
  • read_userget_user_by_id 都是 snake_case,與 URL 路徑的語意相呼應。
  • 這樣的統一命名可讓前端工程師快速對應 API 文件,減少溝通成本。

3. 自動化測試

在 pytest 中,測試函式必須以 test_ 開頭。配合 snake_case,可直接看出測試的焦點:

def test_calculate_discount_returns_correct_value():
    assert calculate_discount(100, 0.2) == 80.0
  • test_calculate_discount_returns_correct_value 完全遵守 snake_case,讓測試報告易於閱讀與維護。

總結

  • 識別字 是程式碼的基礎,必須遵守語法規則(開頭字母或底線、大小寫敏感、避免關鍵字)。
  • snake_case 是 Python 官方推薦的變數與函式命名慣例,具備高可讀性、跨平台一致性與團隊協作友好等優點。
  • 實務上,從 資料分析Web API自動化測試,均可看到 snake_case 的廣泛應用。
  • 透過 lint 工具一致的命名規則,可以有效避免常見陷阱(大寫、連續底線、與關鍵字衝突),提升程式碼品質。

掌握了 snake_case,不只是寫出符合 PEP 8 的程式,更是培養良好程式設計習慣的第一步。未來當你在更大型的專案或多語言環境中工作時,這套命名哲學將持續為你帶來 可讀、可維護、可擴充 的程式碼基礎。祝你在 Python 的旅程中,寫出既美觀又實用的程式!