一元减号 - 优先级高于幂运算 ,因此 -22 等价于 -(22) 得 -4; 右结合,232 等价于 2(32)=512;and/or 与比较、位运算混用时必须加括号避免逻辑错误。

Python运算符优先级表里,** 和 - 谁先算?
负号 -(一元减)比幂运算 ** 优先级更高。这意味着 -2**2 实际算的是 -(2**2),结果是 -4,而不是 (-2)**2 的 4。这是初学者最容易栽跟头的地方——看起来像“负二的平方”,Python 却按“负的(二的平方)”执行。
常见错误现象:print(-2**2) 输出 -4,但预期是 4;math.sqrt(-x**2) 报 ValueError,其实是因为先算 -x**2 得负数,再开方失败。
- 想表达“负数的幂”,必须显式加括号:
(-2)**2 - 想表达“取幂后再取负”,可不加括号,但建议仍写成
-(2**2)提高可读性 -
**是右结合,2**3**2等价于2**(3**2)(即2**9 = 512),不是(2**3)**2
哪些运算符容易因优先级混淆导致逻辑错误?
最常被误用的是 and/or 与比较运算符混用,以及位运算符 &、| 被当成逻辑运算符用。Python 中 and 优先级低于 ==,但高于 or;而 & 优先级远高于 ==,几乎总需要括号。
使用场景:写条件判断(如权限校验、状态组合)、处理整数位掩码时。
立即学习“Python免费学习笔记(深入)”;
-
a == b and c == d or e == f实际等价于((a == b) and (c == d)) or (e == f),但若本意是a == b and (c == d or e == f),就必须加括号 -
if flags & READ | WRITE:错!&先算,|后算,等价于if (flags & READ) | WRITE:—— 这几乎肯定不是你想要的。应写成if (flags & (READ | WRITE)): -
not x in y等价于not (x in y),没问题;但not x == y等价于(not x) == y,非常危险,务必写成not (x == y)或直接用x != y
什么时候括号不是“可选优化”,而是必须加?
括号在三种情况下不是风格问题,而是语义必需:
- 打破默认结合性:比如
10 - 5 - 2是左结合,等于(10 - 5) - 2;若要先算后两项,必须写10 - (5 - 2) - 混合布尔与位运算:只要出现
&、|、^和比较/布尔运算混用,一律加括号,例如(a & MASK) == FLAG、if (x > 0) & (y (注意这里用&是逐位且,不是逻辑且;逻辑且请用and) - 提高可读性且消除歧义:哪怕当前优先级刚好符合预期,只要表达式超过两个操作符,或涉及
**、~、lambda等低频运算符,就加括号。例如(x + y) * z比x + y * z更安全,即使你知道乘法优先
如何快速查证某个表达式的实际计算顺序?
别靠背表,用 ast 模块解析抽象语法树最可靠。对不确定的表达式,丢进 ast.dump() 看结构,一眼就能确认分组关系。
示例:ast.dump(compile("-2**3", "", "eval"), indent=2) 输出中能看到 UAdd 或 USub 节点包裹在 BinOp 外层,证明一元负号确实优先。
- 命令行快速验证:
python -c "import ast; print(ast.dump(ast.parse('a + b * c', mode='eval'), indent=2))" - 交互式环境里,对复杂表达式分步加括号测试,比如先试
(a op b) op c,再试a op (b op c),对比结果 - 不要依赖 IDE 的高亮或自动补全——它们可能美化显示但不反映真实求值顺序
括号不是代码“装饰”,是控制流意图的显式声明。尤其在涉及幂、位运算、布尔混合或多人协作时,宁可多写一对括号,也别赌自己或别人还记得优先级表第几行。











