
最白话版一个空杯子的故事classCup:def__init__(self,water):self.waterwater# 杯里有没有水def__bool__(self):returnself.water0# 没水 → 这个杯子算False# 你面前放着一个空杯子杯子是真实存在的只是没水my_cupCup(water0)# 场景想喝水要么用现有的杯子要么拿个新的装满水your_cup1my_cuporCup(water200)# Python 看 my_cup 没水False以为没杯子又拿了个新杯子your_cup2my_cupifmy_cupisnotNoneelseCup(water200)# 这个写法只认杯子在不在在就直接用你那个空杯子print(or拿出来的杯子是新的吗:,your_cup1isnotmy_cup)# True被偷偷换了print(isNone拿出来的杯子是原杯吗:,your_cup2ismy_cup)# True没换人话翻译你手里明明有个杯子对象存在只是没水。or一看没水直接判定这人没杯子塞给你一个新杯子你原来那个被丢了。is not None只问一句杯子在不在在就还给你那个空杯子。为什么这是 bug业务本意“用户传了过滤器对象就用他的没传才建默认的”。结果用户传了个空过滤器or把它当成没传私自建了个默认过滤器覆盖上去——用户原本的意图被篡改了而且不报错极难查。一句话or看的是东西有没有用is not None看的是东西存不存在。写默认值时你要的是后者。or 根本不看 None它只看 bool()你被直觉骗了。A or B 的真实规则是plaintext如果 bool(A) 是 True → 取 A如果 bool(A) 是 False → 取 B它从头到尾没判断过 A is None。 你这个案例里pythonmy_cup Cup(water0)print(my_cup is None) # False ← 它确实不是Noneprint(bool(my_cup)) # False ← 但它被当成假了因为我们重载了__bool__or 只看第二个结果不看第一个。它看到 bool(my_cup) False就直接取右边的新杯子根本不在乎 my_cup 是不是 None。跑这 4 行你就懂了pythonclass Cup:definit(self, water):self.water waterdefbool(self):return self.water 0my_cup Cup(water0)print(“my_cup is None ?”, my_cup is None) # Falseprint(“bool(my_cup) ?”, bool(my_cup)) # False ← 就是这一行坑了or输出plaintextmy_cup is None ? Falsebool(my_cup) ? False对比一下真相大白表格写法 判断的东西 my_cup 结果my_cup is not None 对象是不是 None True不是 None→ 用原对象 ✅bool(my_cup)or 内部用的 对象有没有水 False没水→ 换新对象 ❌一句话你以为 or 在问 “左边是不是 None”其实它在问 左边真不假。而bool就是我们偷偷改了 “真不假” 的判定标准 —— 让一个真实存在的对象在 Python 眼里变成了 “假”。再补一个常见例子不用类也能看到pythonprint(0 or 99) # 99 因为 bool(0)Falseprint(“” or “hi”) # hi 因为 bool(“”)Falseprint([] or [1,2]) # [1,2] 因为 bool([])Falseprint(None or “默认”) # 默认 因为 bool(None)False你之前写 filters or RetrievalFilters() 能跑通只是因为普通类默认 bool(实例) 永远是 True碰巧没踩坑而已。一旦哪天有人给类加了bool就立刻翻车。