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

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

