
代码跑到这里没报错,也没输出,像被人剪了一刀。
我第一眼一般会去搜 pass。尤其是这种代码:
def sync_user_profile(user_id):
if user_id <= 0:
pass
profile = query_profile(user_id)
push_to_crm(profile)
这段代码看着没毛病,实际很别扭。
pass 在 Python 里什么都不做。不是跳过循环,不是结束函数,也不是忽略错误。它只是告诉解释器:这里语法上必须有一段代码,但我暂时不想写。
Python 对缩进很严格,if、for、while、def、class 后面不能空着。
你这么写会直接报错:
def rebuild_index():
报错大概是:
IndentationError: expected an indented block
所以你先放一个 pass,代码就能跑起来:
def rebuild_index():
pass
这就是 pass 最常见的作用:占位。
我平时写脚本时,经常先把流程骨架搭出来,有些地方还没想清楚,就先用 pass 顶一下。
比如要写一个日志清洗脚本,第一版可能长这样:
def read_raw_lines(path):
with open(path, "r", encoding="utf-8") as f:
for line in f:
yield line.rstrip("\n")
def parse_access_log(line):
pass
def save_bad_line(line, reason):
pass
for raw in read_raw_lines("gateway.log"):
item = parse_access_log(raw)
if item is None:
save_bad_line(raw, "parse failed")
continue
print(item)
这个时候 pass 不是业务逻辑,它只是让我先把主流程跑通。
但这里有个坑。
pass 不等于“以后再说”。
线上代码里出现 pass,我一般会多看两眼。尤其是在异常处理里。
try:
amount = int(row["amount"])
except ValueError:
pass
save_order(row["order_id"], amount)
这段代码很危险。
如果 amount 转换失败,except 里什么都不做,后面还继续用 amount。轻一点报 UnboundLocalError,重一点就是用了上一次循环残留的变量,数据直接脏掉。
这种代码我宁愿写得啰嗦一点:
def parse_amount(row):
raw = row.get("amount")
try:
return int(raw)
except (TypeError, ValueError):
print(f"[bad_amount] order_id={row.get('order_id')} amount={raw!r}")
return None
amount = parse_amount(row)
if amount is None:
continue
save_order(row["order_id"], amount)
异常不是不能吞,但吞之前至少留个痕迹。
pass 放在 except 里,很多时候就是把问题埋了。日志没有,监控没有,数据错了以后再查,基本只能靠猜。
还有一种常见误会,是把 pass 当成 continue。
看这个:
for line in read_raw_lines("pay.log"):
if "timeout" in line:
pass
print(line)
很多人以为遇到 timeout 就跳过了。
不会。
pass 执行完,后面的 print(line) 还会继续跑。它只是站在那里什么都不干。
如果你真要跳过,应该写:
for line in read_raw_lines("pay.log"):
if "timeout" in line:
continue
print(line)
continue 是进入下一轮循环。
break 是结束整个循环。
return 是结束当前函数。
pass 是原地摸鱼。
类里面也能用 pass,这个在写基类、异常类的时候挺常见。
class OrderSyncError(Exception):
pass
这个类没有额外字段,也没有额外方法,只是为了让异常类型更明确。
抛异常时就比直接用 Exception 好查:
def push_order(order):
ok = call_partner(order)
if not ok:
raise OrderSyncError(f"sync failed, order_id={order['id']}")
日志里一眼就能看出来是订单同步异常,不用在一堆通用异常里翻半天。
还有接口草稿,也会用到:
class UserExporter:
def dump_csv(self, users):
pass
def dump_json(self, users):
pass
不过这种代码我不太喜欢长期留着。
如果这个方法真的不允许被调用,我更愿意直接抛异常:
class UserExporter:
def dump_csv(self, users):
raise NotImplementedError("dump_csv has not been implemented")
def dump_json(self, users):
raise NotImplementedError("dump_json has not been implemented")
原因很简单。
pass 会让调用方误以为执行成功了。
NotImplementedError 会让问题早点炸出来。
有些 Bug,早炸是好事,晚炸才麻烦。
Python 里还有个东西容易跟 pass 混在一起:...,也就是 Ellipsis。
def load_config():
...
这个也能占位,但它是一个表达式,不是语句占位符。写类型桩文件、协议定义、临时草稿时有人喜欢用它。
业务代码里我还是更倾向用 pass 或者直接抛 NotImplementedError。别写得太玄,后面接手的人不一定想研究你当时的心情。
我对 pass 的判断比较简单:
临时搭骨架,可以用。
空类、空异常,可以用。
测试里先留个分支,也可以用。
但是异常处理、业务分支、权限判断、金额处理这些地方,看到 pass 就得停一下。
比如这种:
if user["role"] == "admin":
pass
else:
check_permission(user)
这代码不是不能跑,是太容易让人误会。
我宁愿写成:
if user["role"] != "admin":
check_permission(user)
少一个空分支,少一次猜谜。
pass 这个语句本身很小,没什么神秘的。它的作用就是占位,让代码结构先合法。
真正要注意的是,它太安静了。
安静到你以为逻辑处理过了,其实什么都没发生。 线上代码最怕的不是报错,是该报错的时候没报。
以上就是“Python 的 pass 语句有什么作用?”的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。
扫码二维码 获取免费视频学习资料

- 本文固定链接: http://www.phpxs.com/post/14227/
- 转载请注明:转载必须在正文中标注并保留原文链接
- 扫码: 扫上方二维码获取免费视频资料