Python中and和or返回实际操作数而非True/False:a and b在a为假时返a,否则返b;or返首个真值或最后一个值;x为假时y不执行,保障安全访问;not优先级高于and但低于比较运算符,易致逻辑错误。

Python中and和or为什么有时不返回True/False
因为它们根本不是布尔“开关”,而是返回参与运算的**实际操作数**——哪个值被判定为“真/假”就返回哪个。这是短路逻辑的直接结果,也是最常让人困惑的点。
比如a and b:如果a为假(如0、None、空列表),直接返回a,根本不看b;只有a为真,才返回b。or同理,返回第一个为真的值,或最后一个值。
-
"" and [1, 2]→ 返回""(空字符串是假值) -
0 or "fallback"→ 返回"fallback" -
None or [] or "ok"→ 返回"ok"(前两个都假)
写if x and y:时,y什么时候根本不会执行
当x是假值时,y表达式完全跳过——这不只是性能优化,更是避免错误的关键机制。
典型场景:检查对象是否存在再访问属性,或避免除零、空列表索引等。
立即学习“Python免费学习笔记(深入)”;
-
if data and data[0] > 5:—— 如果data为空列表或None,data[0]根本不会求值,不会报IndexError或TypeError -
if user and user.is_active and user.profile.name:—— 链式安全访问,任一环节为假就停住 - 但注意:
y不能是带副作用的函数调用,比如if cond and log_error():,log_error()可能永远不会运行
not的优先级比and高,但比比较运算符低
这不是理论考点,是写错条件时真实报错的根源。Python里not只作用于紧邻的表达式,不像自然语言里能“管很远”。
常见误写:if not x == y: 看起来像“x不等于y”,实际等价于if (not x) == y:——先对x取反,再跟y比较。
- 正确写法永远是:
if x != y:或if not (x == y): - 混合使用时加括号最安全:
if not (a > 0 and b ,而不是<code>if not a > 0 and b (后者被解析为<code>(not a) > 0 and b ) - 优先级顺序(从高到低):
not→and→or,但所有逻辑运算符都低于==、、<code>in等比较运算符
用and/or做“默认值”要小心类型混用
很多人用a or b替代三元表达式取默认值,但一旦a可能是0、0.0、""这些“假值但合法”的情况,就会意外 fallback 到b。
比如配置读取:timeout = config.get("timeout") or 30,如果用户明确设了timeout = 0,本意是“不超时”,结果却变成30。
- 更安全的写法:
timeout = config.get("timeout", 30)(字典方法自带默认) - 或显式判断:
timeout = config["timeout"] if "timeout" in config else 30 -
and也一样:name = user.name and user.name.strip() or "Anonymous",如果user.name是空格字符串,.strip()后变空,又 fallback 了——这种嵌套极易出错
短路逻辑本身很可靠,但把“假值”和“未设置”混为一谈,是多数线上 bug 的源头。









