Python中and和or优先级低于==等比较运算符,因此a == b or c == d and e等价于(a == b) or ((c == d) and e),而非(a == b or c == d) and e。

Python 中 and 和 or 为什么比 == 优先级低?
很多人写 a == b and c 时默认它等价于 (a == b) and c,这是对的;但一旦写成 a == b or c == d and e,就容易误判结合顺序。Python 规定 and/or 的优先级**低于所有比较运算符**(包括 ==、!=、、in 等),所以 a == b or c == d and e 实际等价于 (a == b) or ((c == d) and e),而不是按从左到右直觉理解的 ((a == b) or (c == d)) and e。
常见错误现象:
- 条件判断意外为
True或False,尤其在if中嵌套多个==和逻辑运算符时 - 用
or提供默认值时出错,比如x == None or x == '' or x—— 最后一个x会被当作布尔上下文直接求值,且整个表达式因优先级被拆成(x == None) or (x == '') or x,看似没问题,但若x是非布尔可迭代对象(如列表),可能引发隐式转换问题
实操建议:
- 只要含多个比较和逻辑运算符,一律加括号明确意图,例如写成
(x == 'a') or (x == 'b') - 避免把
or当“默认值运算符”混在比较中,改用if x in ('a', 'b'):或三元表达式y = x if x else default - 用
ast.parse()验证:运行ast.dump(ast.parse("a == b or c == d and e", mode='eval'))可看到抽象语法树中Compare节点始终先于BoolOp构建
赋值运算符 = 不能出现在表达式里?那 := 呢
经典错误:if a = b: 直接报 SyntaxError: invalid syntax,因为 = 是语句级赋值,不允许在表达式中出现。而海象运算符 := 是**唯一允许在表达式中赋值的运算符**,且它的优先级非常低——仅高于 lambda,低于所有其他运算符(包括 or、and、if-else 表达式)。
立即学习“Python免费学习笔记(深入)”;
这意味着:if (x := get_value()) == 42: 是合法的,等价于先执行 x := get_value(),再拿结果跟 42 比较;但 if x := get_value() == 42: 就不对了——它实际是 x := (get_value() == 42),把布尔结果赋给了 x。
实操建议:
-
:=必须加括号才能控制求值时机,否则总被当整体参与右侧运算 - 不要在
and/or链中间裸用,例如result := f() or g()是错的,应写成(result := f()) or g()或更清晰地拆成两行 - 注意作用域:在列表推导式或生成器表达式中使用
:=,赋值变量只在该表达式内有效,不会泄露到外层作用域
位运算符 & | 和布尔运算符 and or 混用会怎样
最典型陷阱:if flag & 1 == 0: 本意是“检查最低位是否为 0”,结果却总是 False(除非 flag 是 0)。因为 == 优先级高于 &,这行代码等价于 if flag & (1 == 0): → flag & False → flag & 0 → 永远为 0 → 转布尔为 False。
类似地,a | b == c 实际是 a | (b == c),不是 (a | b) == c;而 a & b == c & d 会被解析为 (a & (b == c)) & d,完全偏离预期。
实操建议:
- 所有涉及
&、|、^的比较操作,必须显式加括号,例如写成(flag & 1) == 0 - 位运算符之间优先级也有差异:
&高于^,^高于|,所以a ^ b | c等价于(a ^ b) | c,但a & b ^ c是a & (b ^ c) - 如果只是做布尔判断,优先用
and/or;只有明确需要逐位计算时才用位运算符,并确保整条表达式用括号包裹清楚
为什么 -x ** 2 等于 -(x ** 2) 而不是 (-x) ** 2
幂运算 ** 的优先级**高于**一元运算符(如 -、+、~),所以 -x ** 2 总是先算 x ** 2,再取负。这和数学习惯一致(-5² = -25),但和部分程序员直觉冲突(以为负号绑定更紧)。
另一个坑是链式幂运算:2 ** 3 ** 2 不是 (2 ** 3) ** 2 = 8² = 64,而是 2 ** (3 ** 2) = 2⁹ = 512,因为 ** 是右结合的。
实操建议:
- 任何带负号的幂运算都加括号,明确意图:
(-x) ** 2或-(x ** 2) - 避免写
a ** b ** c这类无括号链式表达式,直接拆成两步或加括号说明顺序 - 用
pow(x, y)替代**时,函数调用本身优先级最高,-pow(x, y)就是清晰的取负,不会歧义
复杂点在于,优先级规则不是线性排序表,而是嵌套在语法树结构里的;最容易被忽略的是「比较运算符整体优先级高,但它们之间不满足结合律」——比如 a 是特殊语法糖,等价于 (a ,但这个 and 是解释器自动插入的,不参与常规优先级计算。










