Python入門指南之代碼注釋的三種寫法詳解

一、開篇:好代碼需要好注釋
在上一篇文章中,我們寫出了第一行Python代碼。今天我們要聊一個看似簡單、但很多程序員做了很多年都沒做好的話題:代碼注釋。
注釋是寫在代碼里、但不被Python執(zhí)行的一段文字。它的作用是給讀代碼的人(包括未來的你自己)解釋代碼的含義、邏輯和注意事項。
你可能覺得"我寫的代碼我自己能看懂,不需要注釋"。相信我,三個月后回來看你今天寫的代碼,如果沒有注釋,你大概率會對著屏幕發(fā)呆:“這代碼到底是誰寫的?”——是你自己寫的,但你已經(jīng)忘了當時的思路。
一個編程高手的標志之一,就是能寫出恰到好處的注釋。不是越多越好,也不是越少越好,而是"剛好解釋清楚為什么這樣寫"。
二、Python的三種注釋方式
Python提供了三種寫注釋的方式,每種都有自己的用途。
2.1 單行注釋:井號
這是最常用的注釋方式。以 # 開頭,# 之后直到行尾的所有內(nèi)容都是注釋。
# 這是一個單行注釋
print('Hello, World!') # 這行打印一句話,這也是注釋
# 下面這行代碼計算1到100的和
total = 0
for i in range(1, 101):
total += i # 累加每一個數(shù)字
print(total) # 輸出結(jié)果:5050
單行注釋也可以用來臨時禁用某一行代碼(調(diào)試時特別常用):
print('這條會執(zhí)行')
# print('這條不會執(zhí)行,因為被注釋掉了')
print('這條也會執(zhí)行')
絕大多數(shù)IDE中,選中幾行代碼然后按 Ctrl + /(Mac:Cmd + /)可以快速注釋/取消注釋。
2.2 多行注釋:三個引號
用三個單引號 ''' 或三個雙引號 """ 包裹起來的內(nèi)容,可以作為多行注釋。
''' 這是一個多行注釋 可以跨越多行 Python解釋器會忽略這些內(nèi)容 ''' """ 這也是一個多行注釋 用雙引號也是一樣的效果 可以寫很多行 """
技術(shù)細節(jié):三個引號在Python中實際上創(chuàng)建了一個字符串對象,只是這個字符串沒有被賦值給任何變量,所以Python創(chuàng)建了它之后馬上丟棄。因此嚴格來說這不是"注釋",而是一個"被丟棄的字符串字面量"。但在實際使用中,大家都把它當作多行注釋來用。
三種引號的使用場景:
# 函數(shù)的文檔字符串——這是最正式的用法
def calculate_area(length, width):
"""
計算矩形的面積。
參數(shù):
length (float): 矩形的長度
width (float): 矩形的寬度
返回:
float: 矩形的面積
"""
return length * width
# 代碼頂部的模塊說明
'''
模塊名:用戶管理
功能:處理用戶的注冊、登錄、信息修改等操作
作者:張三
日期:2025-05-30
版本:v1.0
'''
# 臨時注釋掉一大段代碼
'''
print('這段代碼暫時不需要執(zhí)行')
print('先用三個引號把它包起來')
print('等需要的時候再解開')
'''
2.3 文檔字符串(docstring)
文檔字符串是Python中的特殊注釋形式,它用 """...""" 包裹,寫在函數(shù)、類、模塊的第一行。它和普通注釋最大的區(qū)別是:文檔字符串可以被程序讀取。
def greet(name, greeting='你好'):
"""向指定的人打招呼。
Args:
name: 被問候的人的名字
greeting: 問候語,默認為"你好"
Returns:
str: 完整的問候語字符串
Examples:
>>> greet('小明')
'你好,小明!'
>>> greet('小紅', '嗨')
'嗨,小紅!'
"""
return f'{greeting},{name}!'
# 文檔字符串可以通過__doc__屬性被程序訪問
print(greet.__doc__)
# 輸出上面寫的整個文檔
# 也可以用help()函數(shù)查看
help(greet)
# 輸出格式化的文檔
養(yǎng)成寫文檔字符串的好習慣。對于你自己定義的函數(shù)和類,花一分鐘寫一個簡短的文檔字符串,幾個月后你會感謝現(xiàn)在的自己。
三、什么時候該寫注釋
3.1 必須寫注釋的場景
場景一:解釋"為什么",而不是"是什么"
沒有意義的注釋(只是在重復代碼):
x = x + 1 # 將x加1
有價值的注釋(解釋了原因):
x = x + 1 # 補償索引偏移,因為用戶輸入的序號從1開始而不是0
場景二:非顯而易見的算法或邏輯
# 使用埃拉托斯特尼篩法找出所有質(zhì)數(shù)
def sieve_of_eratosthenes(n):
is_prime = [True] * (n + 1)
is_prime[0] = is_prime[1] = False
# 只需要檢查到sqrt(n),因為如果n是合數(shù),
# 它必定有一個因子小于等于sqrt(n)
for i in range(2, int(n ** 0.5) + 1):
if is_prime[i]:
for j in range(i * i, n + 1, i):
is_prime[j] = False
return [i for i in range(2, n + 1) if is_prime[i]]
場景三:帶有特殊限制或注意事項的代碼
# 注意:這個函數(shù)假設輸入列表已按升序排列
# 如果列表未排序,返回的結(jié)果將是錯誤的
def binary_search(sorted_list, target):
# ... 二分查找的實現(xiàn)
場景四:解決特定bug的代碼
# 在Windows上,文件路徑中的反斜杠需要轉(zhuǎn)義
# 使用os.path.join可以避免平臺差異
import os
file_path = os.path.join('data', 'users', 'info.csv')
場景五:TODO和FIXME標記
# TODO: 這里的錯誤處理需要完善,目前只在理想情況下工作 # FIXME: 當用戶名為空時會崩潰,需要添加空值檢查 # HACK: 這是一個臨時方案,等后端接口好了之后要重構(gòu)
3.2 不需要寫注釋的場景
不需要注釋一:代碼本身已經(jīng)足夠清晰
# 不需要注釋 name = '小明' # 設置名字為小明 age = 20 # 設置年齡為20 # 上面的注釋完全是廢話,代碼已經(jīng)說得很清楚了
不需要注釋二:可以從良好命名中直接看出的邏輯
# 不需要注釋——函數(shù)名和變量名已經(jīng)說明了一切
def calculate_average_score(scores):
total = sum(scores)
count = len(scores)
return total / count
不需要注釋三:可以抽取為函數(shù)的復雜邏輯
# ? 一大段需要注釋的復雜代碼
def process_order(order):
# 首先驗證訂單狀態(tài),必須是"待發(fā)貨"
# 然后檢查庫存是否充足
# 如果庫存足夠,扣減庫存
# 最后更新訂單狀態(tài)為"已發(fā)貨"
# ... 20行代碼
pass
# ? 拆分為小函數(shù),函數(shù)名本身就是最好的注釋
def process_order(order):
validate_order(order)
check_inventory(order)
deduct_inventory(order)
update_order_status(order, '已發(fā)貨')
四、注釋的黃金法則
4.1 注釋解釋"為什么",代碼說明"是什么"
# ? 壞注釋:重復代碼
# 遍歷員工列表
for employee in employees:
# 計算工資
salary = employee.hours * employee.hourly_rate
# 打印工資
print(salary)
# ? 好注釋:解釋背后的意圖
for employee in employees:
salary = employee.hours * employee.hourly_rate
# 根據(jù)公司政策,加班時間按1.5倍計算
if employee.hours > 40:
overtime_hours = employee.hours - 40
salary += overtime_hours * employee.hourly_rate * 0.5
print(salary)
4.2 注釋要保持更新
最危險的注釋是過時的注釋——代碼已經(jīng)改了,但注釋沒有同步更新。
# ? 危險的過時注釋
def calculate_tax(income):
# 使用2018年的稅率(實際上2025年已經(jīng)改了?。?
if income < 5000:
return 0
elif income < 8000:
return income * 0.03
# ...
# ? 更好的做法:用清楚的代碼代替注釋
# 稅率表直接來自數(shù)據(jù),代碼本身說明了邏輯
TAX_BRACKETS_2025 = [
(0, 5000, 0),
(5000, 8000, 0.03),
(8000, 17000, 0.10),
# ...
]
def calculate_tax(income):
for lower, upper, rate in TAX_BRACKETS_2025:
if lower <= income < upper:
return (income - lower) * rate
4.3 注釋用英文還是中文
這是中文開發(fā)者經(jīng)常糾結(jié)的問題。我的建議:
- 個人項目 / 學習筆記:用中文,表達更順暢
- 團隊項目 / 開源項目:遵循項目已有的規(guī)范。通常建議用英文(方便國際協(xié)作)
- docstring:如果項目可能開源,建議中英文都寫,或者寫英文
# 個人學習項目——中文注釋完全OK
def binary_search(arr, target):
"""二分查找算法"""
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid # 找到了
elif arr[mid] < target:
left = mid + 1 # 目標在右半部分
else:
right = mid - 1 # 目標在左半部分
return -1 # 沒找到
五、實戰(zhàn):給一段代碼寫注釋
讓我們通過一個實際例子,看看有注釋和沒有注釋的代碼有什么區(qū)別。
5.1 沒有注釋的版本
def f(d, p):
r = []
for k, v in d.items():
if p(v):
r.append(k)
return r
data = {'a': 85, 'b': 42, 'c': 96, 'd': 58, 'e': 73}
print(f(data, lambda x: x >= 60))
你能一眼看出這個程序在做什么嗎?可能需要花點時間。
5.2 加了注釋的版本
"""
學生成績篩選程序
功能:從學生成績字典中篩選出及格(>=60分)的學生名單
"""
def filter_by_criteria(data_dict, check_function):
"""
根據(jù)指定的篩選條件,從字典中篩選出符合條件的鍵。
參數(shù):
data_dict (dict): 待篩選的字典,鍵為學生名,值為成績
check_function (callable): 篩選函數(shù),接受一個值,返回True/False
返回:
list: 符合條件的鍵(學生名)列表
示例:
>>> scores = {'小明': 85, '小紅': 42}
>>> filter_by_criteria(scores, lambda x: x >= 60)
['小明']
"""
passed_keys = [] # 存儲符合條件的學生名
for key, value in data_dict.items():
if check_function(value):
passed_keys.append(key) # 該學生成績符合條件,加入結(jié)果
return passed_keys
# 學生成績數(shù)據(jù)
student_scores = {
'小明': 85,
'小紅': 42,
'小剛': 96,
'小麗': 58,
'小華': 73
}
# 篩選條件:成績大于等于60分(及格線)
def is_passing(score):
return score >= 60
# 執(zhí)行篩選并輸出結(jié)果
passing_students = filter_by_criteria(student_scores, is_passing)
print(f'及格的學生有:{passing_students}')
print(f'及格人數(shù):{len(passing_students)}人')
print(f'不及格人數(shù):{len(student_scores) - len(passing_students)}人')
現(xiàn)在代碼的意思非常清楚了。雖然代碼行數(shù)變多了,但可讀性提升了不止一個檔次。好的命名加上適當?shù)淖⑨專屵@段代碼即使給一個完全沒見過的開發(fā)者看,也能立刻理解它在做什么。
六、各種語言的注釋對比
了解其他語言的注釋方式,有助于你理解Python注釋的特點:
| 語言 | 單行注釋 | 多行注釋 |
|---|---|---|
| Python | # 注釋 | '''注釋''' 或 """注釋""" |
| C/C++/Java | // 注釋 | /* 注釋 */ |
| JavaScript | // 注釋 | /* 注釋 */ |
| SQL | -- 注釋 | /* 注釋 */ |
| Bash/Shell | # 注釋 | : '注釋' |
| HTML | N/A | <!-- 注釋 --> |
Python不像C/Java那樣有專門的多行注釋語法,而是巧妙地將字符串字面量復用作多行注釋。這個設計體現(xiàn)了Python的極簡哲學——少即是多。
七、注釋在調(diào)試中的妙用
7.1 逐段排查bug
當程序出問題時,注釋是最高效的調(diào)試工具之一:
def complex_calculation(data):
# 第一步:數(shù)據(jù)清洗
cleaned_data = clean_data(data)
print(f'清洗后數(shù)據(jù)條數(shù):{len(cleaned_data)}')
# 第二步:數(shù)據(jù)轉(zhuǎn)換(懷疑這里有bug,先注釋掉后面,只看前面的輸出)
# transformed_data = transform_data(cleaned_data)
# print(f'轉(zhuǎn)換后數(shù)據(jù)條數(shù):{len(transformed_data)}')
# 第三步:計算
# result = calculate(transformed_data)
# return result
# 暫時返回None,等排查完bug再恢復
return None
7.2 用注釋做"版本控制"
在學習和實驗階段,可以保留多種寫法做對比:
# 寫法一:使用列表推導式
# squared = [x**2 for x in range(10)]
# 寫法二:使用map函數(shù)
# squared = list(map(lambda x: x**2, range(10)))
# 寫法三:傳統(tǒng)for循環(huán)——當前采用這種寫法,最易讀
squared = []
for x in range(10):
squared.append(x ** 2)
print(squared)
八、本篇小結(jié)
注釋是寫給人的,不是寫給機器的。機器根本看不懂你的注釋,但三個月后的你自己會感激今天的注釋。
核心要點回顧:
- 三種注釋方式:
#單行、'''/"""多行、docstring文檔字符串 - 注釋解釋"為什么",不要只重復"是什么"
- 保持注釋和代碼同步,過時的注釋比沒有注釋更危險
- 好的命名是注釋的替代品——當代碼自己就能說清楚意思時,不需要額外注釋
- 關鍵邏輯必須注釋:算法原理、業(yè)務規(guī)則、特殊限制、已知問題
寫注釋是一種代碼素養(yǎng)。它不是額外的負擔,而是編碼過程中自然的一部分。從今天開始,每寫一段代碼,養(yǎng)成問自己"別人讀到這里能明白嗎"的習慣。下一篇我們將進入Python的基礎語法——縮進規(guī)則和代碼塊規(guī)范。
以上就是Python入門指南之代碼注釋的三種寫法詳解的詳細內(nèi)容,更多關于Python代碼注釋的資料請關注腳本之家其它相關文章!
相關文章
Django自定義插件實現(xiàn)網(wǎng)站登錄驗證碼功能
這篇文章主要為大家詳細介紹了Django自定義插件實現(xiàn)網(wǎng)站登錄驗證碼功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04
淺談算法之最小生成樹Kruskal的Python實現(xiàn)
最小生成樹Kruskal算法可以稱為“加邊法”,初始最小生成樹邊數(shù)為0,每迭代一次就選擇一條滿足條件的最小代價邊,加入到最小生成樹的邊集合里。本文將介紹它的原理,并用Python進行實現(xiàn)2021-06-06
解決linux下使用python打開terminal時報錯的問題
這篇文章主要介紹了linux下使用python打開terminal時報錯,本文通過兩種場景分析給大家詳細講解,需要的朋友可以參考下2023-03-03
python的getattr和getattribute攔截內(nèi)置操作實現(xiàn)
在Python中,getattr和getattribute是用于動態(tài)屬性訪問和自定義屬性訪問行為的重要工具,本文主要介紹了python的getattr和getattribute攔截內(nèi)置操作實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-01-01

