Python 语法精炼9
基本概念:短路求值
-
and、or在 Python 中按照 从左到右 的顺序求值。 -
短路规则:
A and B:先求A,如果A是 假值(falsy),直接返回A(不计算B);否则返回B的值(会计算B)。A or B:先求A,如果A是 真值(truthy),直接返回A(不计算B);否则返回B的值(会计算B)。
注意:and/or 不一定返回 True/False,而是返回其中一个操作数(第一个决定结果的操作数或最后一个操作数)。
真值 / 假值(truthy / falsy)
在布尔上下文中,以下常被视为假值(falsy):
False,None- 数值
0,0.0,0j - 空序列/集合:
'',(),[],{},set() - 自定义对象如果实现
__bool__()返回False或__len__()返回0
其它一般都是真值(truthy)
返回值规则
1 | # or 示例 |
常见用法
默认值 / 回退
常见写法:
1 | name = provided_name or "匿名用户" |
含义:若 provided_name 为假(None / '' / 0 等),使用 "匿名用户"。
注意:当你只想在 None 时使用默认值,而允许空字符串或 0 时保留原值,应改用 if x is None: x = default 或三元表达式 x if x is not None else default。
连续回退
1 | value = a or b or c or d |
等价于“选出第一个 truthy 值”,常用于 config 合并、参数回退等。
条件执行的快速写法(不推荐)
利用 and 的短路做“条件执行”:
1 | condition and do_something() |
如果 condition 为真则执行 do_something(),否则不调用。
注意:这种用法依赖副作用(函数调用),可读性较差,通常建议用显式 if:
1 | if condition: |
旧式三元 / 选择表达式替代(容易出错)
以前有时会见到:
1 | res = cond and value_if_true or value_if_false |
它并不总是等价于 value_if_true if cond else value_if_false,当 value_if_true 为假值时会返回 value_if_false(即误判)。
正确且可读的写法(Python 2.5+):
1 | res = value_if_true if cond else value_if_false |
与函数调用的短路
1 | result = expensive() or fallback() |
如果 expensive() 返回真值则不会调用 fallback()(短路)。这在控制副作用或性能时有用。
短路与强制布尔化
如果你只关心真/假,把表达式包装 bool():
1 | flag = bool(a and b) # 强制得到 True/False |
优先级与求值顺序
not的优先级高于and,and高于or;- 比较运算(如
<,>,==)的优先级高于and/or(即a < b and b < c的语义是(a < b) and (b < c)); - 所有操作按左到右求值;有短路时右侧可能根本不被求值。
示例优先级:
1 | True or False and False |
若优先级会让人混淆,请加括号以明确意图:
1 | res = (a and b) or c |
注意事项
-
把
or当作“只检查 None”会出错1
2x = 0
y = x or 100 # y == 100,但你可能想保留 0如果只想在
None时回退:1
y = x if x is not None else 100
或:
1
y = 100 if x is None else x
-
and/or返回操作数,不是布尔值
在逻辑判断你想得到True/False,请用bool(expr)或if expr:。不要依赖and/or返回类型恰好是布尔值。 -
用
and/or做三元表达式的旧写法可能有 bug。 -
副作用与短路
如果右侧表达式有副作用(修改全局、写文件、网络请求等),短路会影响是否执行这些副作用。要小心使用,必要时写成显式if。 -
对象自定义真值
自定义对象的__bool__或__len__会影响短路结果。设计类时注意这些方法的语义。 -
链式赋值陷阱
表达式a = b or c只是在a中放入结果,并不会改变b或c。如果想修改原变量,需要显式赋值。
示例与对比
1 | # 示例 1:or 作为默认值 |
总结
and/or左到右求值并短路,返回操作数之一,而非总是布尔值。or常用于回退(但要注意假值会触发回退)。and常用于“如果左真则执行右边/返回右边”,但副作用写法可读性差。- 遇到复杂逻辑优先用显式
if/ 三元表达式,避免难以维护的技巧写法。 - 理解假值规则、优先级与短路顺序是避免陷阱的关键。
