010、布尔值判断的暗坑:truthy、falsy、短路逻辑与 None 的正确判法

发布时间:2026/6/22 10:39:38
010、布尔值判断的暗坑:truthy、falsy、短路逻辑与 None 的正确判法 010、布尔值判断的暗坑truthy、falsy、短路逻辑与 None 的正确判法上周帮同事排查一个线上bug场景很简单从Redis里取一个用户配置如果取不到就返回默认值。他写的代码长这样ifnotredis.get(user_config):returndefault_configreturnredis.get(user_config)看着没毛病对吧结果线上炸了——用户配置明明存在但值是0结果not 0为True直接返回了默认配置。这个bug让我想起自己刚入行时踩过的坑今天就把这些暗坑一次性说清楚。truthy和falsyPython的“隐式布尔转换”Python里每个对象都能被当作布尔值使用这就是truthy和falsy的概念。falsy值包括None、False、0、0.0、空字符串、[]空列表、{}空字典、set()空集合、range(0)。其他所有值都是truthy。这里有个容易翻车的地方0和False是falsy但False和0是truthy——因为它们是非空字符串。别笑我真见过有人写if False:然后困惑为什么条件成立。# 这里踩过坑以为空列表是False但判断逻辑写反了items[]ifitems:# 正确写法空列表为falsyprint(有数据)else:print(空列表)短路逻辑and和or的“偷懒”机制短路逻辑是Python优化布尔表达式的手段但用不好就是坑。and遇到第一个falsy就停or遇到第一个truthy就停。# 别这样写依赖短路逻辑做条件赋值可读性极差resultaorborc# 返回第一个truthy值如果全是falsy返回最后一个# 更清晰的写法resultaifaelsebifbelsec# 虽然也不推荐但至少意图明确短路逻辑最常见的坑是or返回的是第一个truthy值不一定是布尔值。比如nameuser_inputor默认用户# 如果user_input是空字符串返回默认用户# 但如果user_input是0也返回默认用户——这可能不是你要的None的正确判法别用not用is回到开头的bug正确的做法是显式判断None# 正确写法用is None判断configredis.get(user_config)ifconfigisNone:returndefault_configreturnconfig为什么不用not config因为not会把所有falsy值都当成“不存在”包括0、False、空字符串等。如果你明确要判断“值为None”就用is None。# 这里踩过坑用not判断None结果0被误判defget_user_score(user_id):scorecache.get(fscore:{user_id})ifscoreisNone:# 正确只判断Nonereturn0returnscore实战中的“三态”判断实际开发中经常遇到“三态”场景值存在且为真、值存在但为假、值不存在。这时候if value和if value is None都不够用。# 别这样写无法区分值为False和值不存在ifconfig:# 处理配置else:# 这里可能是config为False也可能是config为None# 正确做法先判断存在性再判断值ifconfigisnotNone:ifconfig:# 配置为真else:# 配置为假0、False、空字符串等else:# 配置不存在函数返回值判断的陷阱很多内置函数和库函数在“没找到”时返回None但有些返回-1或空列表。比如str.find()找不到返回-1而-1是truthy。# 这里踩过坑用if判断str.find()的结果texthello worldiftext.find(python):# 返回-1-1是truthy条件成立print(找到了)# 实际上没找到# 正确写法iftext.find(python)!-1:print(找到了)个人经验建议判断None永远用isis None和is not None别用更别用not。is比快而且语义更清晰。判断空容器用if not比如if not items:比if len(items) 0:更Pythonic前提是你确定items是列表且不会为None。避免链式or赋值a or b or c这种写法虽然简洁但可读性差而且容易误判falsy值。用三元表达式或显式if-else。写单元测试覆盖边界值至少测试None、0、False、空字符串、空列表这五种情况。我见过太多bug都是因为没测边界值。类型注解静态检查用Optional[int]明确表示可能为None配合mypy能在编译期发现很多问题。最后说一句Python的隐式布尔转换是双刃剑用好了代码简洁用不好就是线上事故。记住一个原则——显式优于隐式当你不确定时就写清楚判断条件。