if else 一层套一层,代码看着没报错,人先看烦了。
这种代码我平时一进项目就能闻出来。不是功能写不出来,是分支一多,判断散了,后面谁改谁心虚。尤其 Python,本来语法就轻,结果被写成了流程图,确实有点亏。
下面这 10 个写法,不是拿来秀技巧的,都是我平时真会拿来替换 if else 的。你不一定一次全用上,但哪怕先换掉两三个,代码味道都会顺不少。
1. 能用映射表,就别一路问下去
很多人写状态分发,第一反应就是 if elif elif。
def send_notice(channel, content):
if channel == "sms":
return f"短信发送: {content}"
elif channel == "email":
return f"邮件发送: {content}"
elif channel == "push":
return f"站内推送: {content}"
else:
raise ValueError(f"未知渠道: {channel}")
这类代码一旦渠道变多,就开始发散。直接收成表:
def _send_sms(content):
return f"短信发送: {content}"
def _send_email(content):
return f"邮件发送: {content}"
def _send_push(content):
return f"站内推送: {content}"
SENDERS = {
"sms": _send_sms,
"email": _send_email,
"push": _send_push,
}
def send_notice(channel, content):
handler = SENDERS.get(channel)
if not handler:
raise ValueError(f"未知渠道: {channel}")
return handler(content)
后面加渠道,不动主流程,这种代码维护起来明显轻松。
2. 提前返回,别把正常逻辑缩进到地板下面
我看代码时,最烦的不是 if 多,是主逻辑被包了四层。
def create_user(payload):
if payload:
if payload.get("mobile"):
if len(payload["mobile"]) == 11:
return {"ok": True, "mobile": payload["mobile"]}
return {"ok": False}
这种先把异常路口打掉:
def create_user(payload):
if not payload:
return {"ok": False, "reason": "空参数"}
mobile = payload.get("mobile")
if not mobile:
return {"ok": False, "reason": "手机号缺失"}
if len(mobile) != 11 or not mobile.isdigit():
return {"ok": False, "reason": "手机号格式不对"}
return {"ok": True, "mobile": mobile}
主路径更直。排查线上问题时,这种写法日志也更好补。
3. 三元表达式,处理一眼能看懂的小判断
别滥用,但也别不用。
status_text = "已支付" if paid else "待支付"
这种就很好。可你要是写成三层嵌套:
status_text = "已完成" if done else "处理中" if running else "失败"
我一般不太信。不是不能跑,是两周后你自己都得眯着眼看。三元表达式只适合短、平、单分支。
4. 用 dict.get() 兜底,少写一截存在性判断
这招太常见,但很多人还是喜欢先 if key in data。
def build_export_row(record):
return {
"name": record.get("name", ""),
"mobile": record.get("mobile", ""),
"age": record.get("age", 0),
"city": record.get("city", "未知"),
}
尤其做导入导出、字段清洗,这种写法很顺。别一边判断 key 存不存在,一边再取值,代码平白长一倍。
5. set 处理多值判断,比连写 or 干净
这个我在权限校验、状态过滤里用得很多。
def can_retry(status):
if status in {"FAILED", "TIMEOUT", "CANCELLED"}:
return True
return False
替换掉这种:
def can_retry(status):
if status == "FAILED" or status == "TIMEOUT" or status == "CANCELLED":
return True
return False
后者没技术含量,就是笨。状态再多一点,自己都不想看。
6. all() / any() 收掉连续条件
表单校验很容易写成 if 地毯。
def valid_order(data):
return all([
data.get("user_id"),
data.get("sku_id"),
data.get("amount") is not None,
data.get("amount", 0) > 0,
])
或者查风控条件时:
def hit_risk_rule(tags):
return any([
"fake_device" in tags,
"proxy_ip" in tags,
"black_uid" in tags,
])
这种比一串 and、or 更聚焦。条件一眼能扫完。
7. match-case 该上就上,别死守 if elif
Python 3.10 之后,这个在命令分发、消息类型处理上很好用。
def parse_event(event):
match event.get("type"):
case "pay":
return f"处理支付单:{event.get('order_id')}"
case "refund":
return f"处理退款单:{event.get('order_id')}"
case "close":
return f"关闭订单:{event.get('order_id')}"
case _:
return f"忽略事件:{event.get('type')}"
这种多分支、同一维度判断的场景,match-case 比 if elif 更像回事。 但也别见到分支就上,条件不在一个维度上,硬写反而更拧巴。
8. 多态或者 策略类,专治“功能越加越长”
这招适合业务稍微复杂一点的时候。比如优惠计算。
class Coupon:
def calc(self, amount):
raise NotImplementedError
class FullCutCoupon(Coupon):
def calc(self, amount):
return amount - 30 if amount >= 200 else amount
class DiscountCoupon(Coupon):
def calc(self, amount):
return round(amount * 0.9, 2)
class NoCoupon(Coupon):
def calc(self, amount):
return amount
def settle_amount(amount, coupon: Coupon):
return coupon.calc(amount)
你当然也能写成:
if coupon_type == "full_cut":
...
elif coupon_type == "discount":
...
开始就两种券时,没人觉得有问题。到第五种、第八种的时候,味道就出来了。
9. 用异常处理中断错误分支,别拿返回值硬撑
很多脚本喜欢这么写:
def load_price(row):
if "price" in row:
if str(row["price"]).isdigit():
return int(row["price"])
return 0
这种静默吞错,后面对账最容易出事。我更喜欢让脏数据尽早暴露:
def load_price(row):
raw = str(row["price"]).strip()
if not raw.isdigit():
raise ValueError(f"非法价格: {raw}")
return int(raw)
批处理里可以配合日志一起用:
def parse_rows(rows):
result = []
for idx, row in enumerate(rows, start=1):
try:
result.append(load_price(row))
except Exception as e:
print(f"[warn] 第{idx}行跳过: {e}")
return result
错误就是错误,别装成正常分支混过去。
10. 把判断抽成小函数,别把业务主线写成判断合集
这个最朴素,也最容易被忽略。很多函数难看,不是因为 if else,多半是判断和动作搅一锅了。
def is_new_user(user):
return user.get("register_days", 999) <= 7
def is_high_value(user):
return user.get("paid_amount", 0) >= 1000
def should_give_coupon(user):
return is_new_user(user) and is_high_value(user)
def process_user(user):
if should_give_coupon(user):
return {"coupon": 50, "tag": "重点转化"}
return {"coupon": 0, "tag": "普通用户"}
主流程只保留判断结果,细节下沉。后面规则变了,改小函数,不要每次都去主函数里刨。
我见过不少 Python 代码,表面问题是 if else 太多,实际问题是判断和动作没分开,异常和正常路径混着走,分发逻辑全堆在一处。