如何在Python中实现类SQL NULL风格的三值逻辑?
实现SQL风格的三值逻辑
由于Python原生的and/or是短路运算符,其行为由对象的布尔值决定,无法直接重载以适配三值逻辑的完整规则,因此我们可以通过自定义单例类实现符合SQL NULL逻辑的三值布尔类型,使用重载的运算符替代原生逻辑运算符,同时满足is判断的需求。
实现代码
class TriBool: """实现SQL风格三值逻辑的布尔类型(True/False/Unknown)""" def __init__(self, value): self._value = value # 0: False, 1: True, 2: Unknown # 定义单例实例 TRUE = None FALSE = None UNKNOWN = None def __repr__(self): return {0: "TriBool.FALSE", 1: "TriBool.TRUE", 2: "TriBool.UNKNOWN"}[self._value] def __eq__(self, other): return isinstance(other, TriBool) and self._value == other._value def __and__(self, other): """重载&运算符,对应三值逻辑的AND""" # 自动转换普通布尔值为TriBool实例 if not isinstance(other, TriBool): other = TriBool.TRUE if other else TriBool.FALSE # 对应真值表的AND规则 lookup = { (1, 1): 1, (1, 2): 2, (1, 0): 0, (2, 1): 2, (2, 2): 2, (2, 0): 0, (0, 1): 0, (0, 2): 0, (0, 0): 0 } return TriBool(lookup[(self._value, other._value)]) def __rand__(self, other): """处理左操作数不是TriBool的情况(如True & UNKNOWN)""" return self & other def __or__(self, other): """重载|运算符,对应三值逻辑的OR""" if not isinstance(other, TriBool): other = TriBool.TRUE if other else TriBool.FALSE # 对应真值表的OR规则 lookup = { (1, 1): 1, (1, 2): 1, (1, 0): 1, (2, 1): 1, (2, 2): 2, (2, 0): 2, (0, 1): 1, (0, 2): 2, (0, 0): 0 } return TriBool(lookup[(self._value, other._value)]) def __ror__(self, other): """处理左操作数不是TriBool的情况(如False | UNKNOWN)""" return self | other def __invert__(self): """重载~运算符,对应三值逻辑的NOT""" lookup = {1: 0, 0: 1, 2: 2} return TriBool(lookup[self._value]) def __bool__(self): """禁止隐式转换为普通布尔值,避免混淆""" raise TypeError("TriBool cannot be implicitly converted to bool. Use explicit comparison instead.") # 初始化单例 TriBool.TRUE = TriBool(1) TriBool.FALSE = TriBool(0) TriBool.UNKNOWN = TriBool(2)
使用示例
# 基础赋值 t = TriBool.TRUE f = TriBool.FALSE n = TriBool.UNKNOWN # AND运算 print(t & t) # TriBool.TRUE print(t & n) # TriBool.UNKNOWN print(n & f) # TriBool.FALSE # OR运算 print(f | n) # TriBool.UNKNOWN print(n | t) # TriBool.TRUE print(n | n) # TriBool.UNKNOWN # NOT运算 print(~t) # TriBool.FALSE print(~n) # TriBool.UNKNOWN # is判断 print(t is TriBool.TRUE) # True print(n is TriBool.FALSE) # False
关键说明
- 单例设计:通过类属性维护三个唯一实例,确保
is判断可以准确识别状态。 - 运算符重载:用
&替代and、|替代or、~替代not,完全匹配你提供的真值表规则。 - 类型兼容:支持与普通布尔值混合运算,自动转换为TriBool实例。
- 避免混淆:禁止隐式转换为普通布尔值,防止因原生短路逻辑导致的非预期行为。
内容的提问来源于stack exchange,提问作者Artimis Fowl
相关产品推荐
相关产品推荐

