Python 第五课:逻辑运算符、短路求值与链式比较
课程概述
本节课我们将深入探讨 Python 中三个最重要的逻辑运算符——and、or 和 not的工作原理,以及与它们密切相关的短路求值(Short-circuit Evaluation,也称为最小化求值)机制。我们还将详细学习 Python 特有的链式比较(Chained Comparisons)语法,这是 Python 语言中最优雅的特性之一。此外,本课还将涵盖 Python 中所有对象的布尔值规则、真值测试(Truth Value Testing),以及如何利用逻辑运算符的特性编写更加简洁、高效和安全的代码。本课程所有内容基于 Python 3.11 编写,涵盖了 Python 3.11 中关于布尔运算和比较操作的最新实现细节和优化。
逻辑运算符是所有编程语言的基石之一,它们构成了条件判断、循环控制和程序逻辑的核心。Python 的逻辑运算符相比其他语言有一些独特的设计:Python 使用英语单词 and、or、not 而不是 &&、||、! 这样的符号,这使得代码更接近自然语言,可读性更强。更重要的是,Python 的逻辑运算符遵循短路求值原则,这不仅提高了代码效率,还为编写安全的代码提供了独特的手段。
逻辑运算符基础
and(逻辑与)
and 运算符当且仅当两个操作数都为 True 时结果才为 True。在任何其他情况下,结果都是 False。
# and 运算符的真值表
print("=" * 50)
print("and 运算符真值表")
print("=" * 50)
print(f"True and True = {True and True}")
print(f"True and False = {True and False}")
print(f"False and True = {False and True}")
print(f"False and False = {False and False}")
print()
# and 运算符返回的是最后一个求值的表达式,而不是单纯的 True/False
print("and 返回的值:")
print(f"1 and 2 = {1 and 2}") # 返回 2
print(f"1 and 0 = {1 and 0}") # 返回 0
print(f"0 and 1 = {0 and 1}") # 返回 0
print(f"'a' and 'b' = {'a' and 'b'}") # 返回 'b'
print(f"'' and 'b' = {'' and 'b'}") # 返回 ''
or(逻辑或)
or 运算符当任意一个操作数为 True 时结果就为 True。只有两个操作数都为 False 时结果才为 False。
# or 运算符的真值表
print("=" * 50)
print("or 运算符真值表")
print("=" * 50)
print(f"True or True = {True or True}")
print(f"True or False = {True or False}")
print(f"False or True = {False or True}")
print(f"False or False = {False or False}")
print()
# or 运算符返回的是第一个求值为真的表达式
print("or 返回的值:")
print(f"1 or 2 = {1 or 2}") # 返回 1
print(f"0 or 2 = {0 or 2}") # 返回 2
print(f"0 or '' = {0 or ''}") # 返回 ''
print(f"'a' or 'b' = {'a' or 'b'}") # 返回 'a'
print(f"'' or 'b' = {'' or 'b'}") # 返回 'b'
not(逻辑非)
not 运算符是一元运算符,用于取反布尔值。
# not 运算符的真值表
print("=" * 50)
print("not 运算符真值表")
print("=" * 50)
print(f"not True = {not True}")
print(f"not False = {not False}")
print()
# not 返回的是布尔值
print("not 返回的值(总是布尔值):")
print(f"not 1 = {not 1}") # False
print(f"not 0 = {not 0}") # True
print(f"not 'a' = {not 'a'}") # False
print(f"not '' = {not ''}") # True
短路求值(Short-circuit Evaluation)详解
短路求值是逻辑运算符最重要的特性之一。理解短路求值对于编写高效、安全的 Python 代码至关重要。
and 的短路行为
当使用 and 连接多个表达式时,Python 从左到右计算每个表达式。一旦遇到值为假的表达式,就立即返回该值,不再继续计算后续表达式。这是因为只要有一个操作数为 False,and 的结果就一定是 False。
print("=" * 50)
print("and 的短路求值演示")
print("=" * 50)
def trace(value, name):
"""跟踪函数调用"""
print(f" [调用 trace({value!r}, '{name}')]")
return value
print("测试 1:trace(False, 'a') and trace(5, 'b')")
result = trace(False, "a") and trace(5, "b")
print(f"结果:{result}")
print("解释:第一个值为 False,直接返回,不再计算第二个表达式\n")
print("测试 2:trace(True, 'a') and trace(10, 'b')")
result = trace(True, "a") and trace(10, "b")
print(f"结果:{result}")
print("解释:第一个值为 True,继续计算第二个表达式\n")
or 的短路行为
当使用 or 连接多个表达式时,Python 从左到右计算每个表达式。一旦遇到值为真的表达式,就立即返回该值,不再继续计算后续表达式。这是因为只要有一个操作数为 True,or 的结果就一定是 True。
print("=" * 50)
print("or 的短路求值演示")
print("=" * 50)
def trace(value, name):
"""跟踪函数调用"""
print(f" [调用 trace({value!r}, '{name}')]")
return value
print("测试 1:trace(True, 'a') or trace(5, 'b')")
result = trace(True, "a") or trace(5, "b")
print(f"结果:{result}")
print("解释:第一个值为 True,直接返回,不再计算第二个表达式\n")
print("测试 2:trace(False, 'a') or trace(10, 'b')")
result = trace(False, "a") or trace(10, "b")
print(f"结果:{result}")
print("解释:第一个值为 False,继续计算第二个表达式\n")
短路求值的实际应用
应用一:安全的默认值赋值
# 场景:根据配置值或默认值进行初始化
# 不使用短路求值(不安全)
# config = get_config() # 如果返回 None 会出问题
# timeout = config.timeout # AttributeError
# 使用短路求值(安全)
def get_config():
return None
config = get_config()
timeout = config.timeout if config else 30
print(f"超时时间:{timeout} 秒")
# 或者使用 or 运算符
config = {"timeout": 60} # 模拟获取到的配置
timeout = config.get("timeout") or 30
print(f"超时时间:{timeout} 秒")
应用二:避免除零错误
# 场景:计算比率,但要避免除数为零
def safe_divide(a, b):
# 使用短路求值避免除零
return (b != 0) and (a / b) or "除数不能为零"
print(safe_divide(10, 2)) # 5.0
print(safe_divide(10, 0)) # 除数不能为零
# 更推荐的方式
def safe_divide_v2(a, b):
if b != 0:
return a / b
return "除数不能为零"
print(safe_divide_v2(10, 2)) # 5.0
print(safe_divide_v2(10, 0)) # 除数不能为零
应用三:链式函数调用
# 场景:只有对象存在且有效时才调用其方法
class User:
def __init__(self, profile):
self.profile = profile
def get_name(self):
return self.profile.get("name") if self.profile else None
user_data = {"name": "张三", "age": 25}
# 传统写法(不安全)
# user = get_user(id)
# name = user.get_name() # 如果 user 为 None 会崩溃
# 使用短路求值
user = User(user_data)
name = user and user.profile and user.profile.get("name")
print(f"用户名:{name}")
# 或者使用更清晰的写法
user = None
name = user and user.profile and user.profile.get("name")
print(f"用户名:{name}") # None(不会报错)
应用四:条件执行
# 场景:只有在满足前置条件时才执行操作
def process_data(data):
# 只有 data 非空且类型正确时才处理
return data and isinstance(data, list) and [x * 2 for x in data]
print(process_data([1, 2, 3])) # [2, 4, 6]
print(process_data([])) # [](空列表,但类型正确)
print(process_data("hello")) # None(类型不对)
真值测试(Truth Value Testing)
Python 中的所有对象都可以进行真值测试,即在布尔上下文中判断对象的真假。
哪些值是假的?
print("=" * 50)
print("Python 中的假值(Falsy Values)")
print("=" * 50)
print("以下值在布尔测试中为 False:")
print()
# 常数
print("1. 常数:None, False")
print(f" bool(None) = {bool(None)}")
print(f" bool(False) = {bool(False)}")
print()
# 数字类型
print("2. 数字类型:0, 0.0, 0j, Decimal(0), Fraction(0, 1)")
print(f" bool(0) = {bool(0)}")
print(f" bool(0.0) = {bool(0.0)}")
print(f" bool(0j) = {bool(0j)}")
print()
# 序列和集合
print("3. 空序列/集合:'', (), [], {{}}, set()")
print(f" bool('') = {bool('')}")
print(f" bool(()) = {bool(())}")
print(f" bool([]) = {bool([])}")
print(f" bool({{}}) = {bool({})}")
print(f" bool(set()) = {bool(set())}")
哪些值是真的?
print("=" * 50)
print("Python 中的真值(Truthy Values)")
print("=" * 50)
print("除了上述假值以外,所有其他值都是真值:")
print()
print("1. 非零数字:")
print(f" bool(1) = {bool(1)}")
print(f" bool(-1) = {bool(-1)}")
print(f" bool(0.001) = {bool(0.001)}")
print()
print("2. 非空字符串:")
print(f" bool(' ') = {bool(' ')}") # 注意:空格字符串也是真值
print(f" bool('False') = {bool('False')}") # 字符串 'False' 也是真值
print()
print("3. 非空序列/集合:")
print(f" bool([0]) = {bool([0])}") # 包含 0 的列表也是真值
print(f" bool('hello') = {bool('hello')}")
print(f" bool({{'a': 1}}) = {bool({'a': 1})}")
自定义对象的真值测试
# 通过定义 __bool__ 方法来控制对象的真值
class MyClass:
def __init__(self, value):
self.value = value
def __bool__(self):
return self.value > 0
obj1 = MyClass(10)
obj2 = MyClass(-5)
obj3 = MyClass(0)
print(f"obj1 (value=10) 的真值:{bool(obj1)}") # True
print(f"obj2 (value=-5) 的真值:{bool(obj2)}") # False
print(f"obj3 (value=0) 的真值:{bool(obj3)}") # False
# 如果没有定义 __bool__,Python 会使用 __len__
class MyList:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
lst = MyList([1, 2, 3])
print(f"MyList([1,2,3]) 的真值:{bool(lst)}") # True(有 3 个元素)
lst_empty = MyList([])
print(f"MyList([]) 的真值:{bool(lst_empty)}") # False(没有元素)
链式比较(Chained Comparisons)
链式比较是 Python 最优雅的特性之一。它允许你将多个比较操作串联在一起,形成一个清晰、易读的比较表达式。
链式比较的基本原理
print("=" * 50)
print("链式比较")
print("=" * 50)
# 基本链式比较
x = 5
print(f"x = {x}")
print(f"0 < x < 10 = {0 < x < 10}")
print(f"0 < x < 3 = {0 < x < 3}")
# Python 实际上将链式比较解释为:
print(f"\n等价于:(0 < x) and (x < 10) = {(0 < x) and (x < 10)}")
链式比较的工作原理
# Python 对链式比较的特殊处理
# 0 < x < 10 不会先计算 (0 < x) 得到 True/False,
# 然后再与 10 比较
# Python 会将其转换为 (0 < x) and (x < 10)
# 重要:x 只会计算一次
print("演示 x 只计算一次:")
x = 5
def get_x():
print(f" [调用 get_x()]")
return x
print("计算 0 < get_x() < 10:")
result = 0 < get_x() < 10
print(f"结果:{result}")
print("注意:get_x() 只被调用了一次!")
各种链式比较模式
# 1. 简单数值范围检查
age = 25
print(f"年龄 {age} 是否在 18-65 岁之间:{18 <= age <= 65}")
# 2. 多个连续比较
x = 5
print(f"x = {x}, 0 < x < 10 = {0 < x < 10}")
# 3. 三个以上的链式比较
y = 15
print(f"y = {y}, 0 < x < 10 < y < 20 = {0 < x < 10 < y < 20}")
# 4. 同一变量多次出现在链中
a = 10
print(f"a = {a}, 0 < a < 20 > 5 = {0 < a < 20 > 5}")
# 5. 不同比较运算符的链式组合
x = 5
print(f"x = {x}, x == 5 >= 3 != 0 = {x == 5 >= 3 != 0}")
链式比较的实际应用
# 应用一:区间判断
def get_score_level(score):
"""根据分数返回等级"""
if 90 <= score <= 100:
return "A"
elif 80 <= score < 90:
return "B"
elif 70 <= score < 80:
return "C"
elif 60 <= score < 70:
return "D"
elif 0 <= score < 60:
return "F"
else:
return "无效分数"
scores = [95, 85, 75, 65, 55, 105, -5]
for s in scores:
print(f"分数 {s:>4} => 等级 {get_score_level(s)}")
# 应用二:边界检查
def is_valid_coordinate(lat, lon):
"""检查坐标是否有效"""
return -90 <= lat <= 90 and -180 <= lon <= 180
coords = [
(0, 0), (45.5, 120.3), (91, 0), (0, 181), (35.3, 139.7) # 东京
]
print("\n坐标有效性检查:")
for lat, lon in coords:
valid = is_valid_coordinate(lat, lon)
print(f"({lat:>6}, {lon:>7}) => {'有效' if valid else '无效'}")
链式比较与运算符优先级
# 链式比较的优先级规则
# a < b == c 会被解析为 (a < b) and (b == c)
# 而不是 a < (b == c)
a, b, c = 1, 2, 2
print(f"a = {a}, b = {b}, c = {c}")
print(f"a < b == c : {a < b == c}") # (1 < 2) and (2 == 2) = True
print(f"等价于:(a < b) and (b == c) = {(a < b) and (b == c)}")
# 使用括号改变优先级
print(f"\na < (b == c) : {a < (b == c)}")
and、or、not 的组合使用
优先级:not > and > or
print("=" * 50)
print("逻辑运算符优先级")
print("=" * 50)
print("优先级:not > and > or")
print()
# not 优先级最高
print("示例 1:not True and False")
print(f"结果:{not True and False}") # (not True) and False = False and False = False
print(f"等价于:(not True) and False = {(not True) and False}")
print()
# and 优先级高于 or
print("示例 2:True or False and False")
print(f"结果:{True or False and False}") # True or (False and False) = True or False = True
print(f"等价于:True or (False and False) = {True or (False and False)}")
print()
# 使用括号改变优先级
print("示例 3:(True or False) and False")
print(f"结果:{(True or False) and False}") # True and False = False
复杂的逻辑表达式
# 组合使用 and、or、not
age = 25
income = 50000
has_credit = False
is_employed = True
# 判断是否可以申请信用卡
can_apply = (
(age >= 18 and age <= 65) # 年龄在 18-65 岁之间
and (income > 30000 or has_credit) # 收入高于 30000 或者有其他信用卡
and is_employed # 当前在就业状态
)
print(f"年龄={age}, 收入={income}, 有信用卡={has_credit}, 在职={is_employed}")
print(f"可以申请信用卡:{can_apply}")
德摩根定律的 Python 实现
德摩根定律(De Morgan’s Laws)是逻辑代数的基本定律:
# 德摩根定律:
# not (A and B) == (not A) or (not B)
# not (A or B) == (not A) and (not B)
print("=" * 50)
print("德摩根定律验证")
print("=" * 50)
A, B = True, False
print(f"A = {A}, B = {B}")
print()
print(f"not (A and B) = {not (A and B)}")
print(f"(not A) or (not B) = {(not A) or (not B)}")
print(f"相等:{not (A and B) == (not A) or (not B)}")
print()
print(f"not (A or B) = {not (A or B)}")
print(f"(not A) and (not B) = {(not A) and (not B)}")
print(f"相等:{not (A or B) == (not A) and (not B)}")
短路求值的高级应用
应用一:级联默认值赋值
# 使用 or 实现级联默认值
def get_connection_string(primary, secondary, fallback):
"""获取数据库连接字符串"""
return primary or secondary or fallback
primary = "" # 主数据库不可用
secondary = "" # 备用数据库也不可用
fallback = "sqlite:///default.db"
result = get_connection_string(primary, secondary, fallback)
print(f"连接字符串:{result}")
应用二:函数存在性检查
# 检查函数是否存在并调用
class Calculator:
def add(self, a, b):
return a + b
def subtract(self, a, b):
return a - b
calc = Calculator()
# 传统写法
if hasattr(calc, "multiply"):
result = calc.multiply(5, 3)
else:
result = "方法不存在"
# 使用 getattr 和短路求值(更 Pythonic)
multiply_func = getattr(calc, "multiply", None)
result = multiply_func and multiply_func(5, 3) or "方法不存在"
print(f"multiply 结果:{result}")
# 验证 add 方法存在
add_func = getattr(calc, "add", None)
result = add_func and add_func(5, 3) or "方法不存在"
print(f"add 结果:{result}")
应用三:防止 KeyError
# 使用 and 链安全访问嵌套字典
data = {
"user": {
"profile": {
"name": "张三",
"settings": {
"theme": "dark"
}
}
}
}
# 不安全的方式(可能 KeyError)
# theme = data["user"]["profile"]["settings"]["theme"]
# 使用短路求值的安全方式
theme = (
data
and data.get("user")
and data["user"].get("profile")
and data["user"]["profile"].get("settings")
and data["user"]["profile"]["settings"].get("theme")
)
print(f"主题:{theme}")
# 更简洁的替代方案(Python 3.10+)
# 使用 | 运算符(需要注意,这只对字典有效)
# theme = data.get("user", {}).get("profile", {}).get("settings", {}).get("theme")
# 使用异常处理(最安全的方式)
try:
theme = data["user"]["profile"]["settings"]["theme"]
except (KeyError, TypeError):
theme = None
print(f"主题(try-except):{theme}")
Python 3.11 中的改进
Python 3.11 对布尔运算和比较操作进行了一些优化:
布尔运算的性能优化
# Python 3.11 中布尔运算的性能改进
# True 和 False 现在是 singletons(单例),比较操作更快
a = True
b = False
# is 比较
print(f"a is True : {a is True}") # True
print(f"b is False : {b is False}") # True
# 布尔类型的内部优化
import sys
print(f"\nbool 的缓存大小:{sys.maxsize}") # 仅供参考
比较操作的优化
# Python 3.11 中链式比较的字节码优化
x = 5
print(f"0 < x < 10 = {0 < x < 10}")
# Python 3.11 中对 NaN 的比较处理
import math
nan = float('nan')
print(f"\nnan 的比较:")
print(f"nan < 5 = {nan < 5}") # False
print(f"nan > 5 = {nan > 5}") # False
print(f"nan == nan = {nan == nan}") # False(NaN 不等于自身!)
print(f"\nnan 与其他值的逻辑运算:")
print(f"nan and True = {nan and True}") # True
print(f"nan or False = {nan or False}") # False
短路求值与 lambda/列表推导式
# 在列表推导式中使用短路求值
data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 只处理非零元素
result = [x * 2 for x in data if x != 0]
print(f"非零元素的加倍:{result}")
# 使用 and 实现条件过滤
result = [x * 2 for x in data if x and x % 2 == 0] # x 非零且为偶数
print(f"非零偶数的加倍:{result}")
# 短路求值在列表推导式中的作用
values = [0, None, "", 1, 2, None, 3]
# 只保留真值
filtered = [v for v in values if v]
print(f"真值过滤:{filtered}")
综合练习题
练习一:布尔运算综合测试
"""
布尔运算综合测试
测试短路求值、链式比较和逻辑组合
"""
def test_short_circuit():
"""测试短路求值"""
print("=" * 60)
print("测试 1:短路求值")
print("=" * 60)
call_count = {"a": 0, "b": 0}
def make_func(name):
def func():
call_count[name] += 1
print(f" [调用 {name}()]")
return True # 总是返回 True
return func
a = make_func("a")
b = make_func("b")
print("a() and b():")
call_count = {"a": 0, "b": 0}
result = a() and b()
print(f"结果:{result},a 调用次数:{call_count['a']},b 调用次数:{call_count['b']}")
print()
def make_func_false(name):
def func():
call_count[name] += 1
print(f" [调用 {name}()]")
return False
return func
a_false = make_func_false("a")
b = make_func("b")
print("a_false() and b():")
call_count = {"a": 0, "b": 0}
result = a_false() and b()
print(f"结果:{result},a 调用次数:{call_count['a']},b 调用次数:{call_count['b']}")
def test_or_short_circuit():
"""测试 or 的短路求值"""
print()
print("=" * 60)
print("测试 2:or 的短路求值")
print("=" * 60)
call_count = {"a": 0, "b": 0}
def make_func(name, return_value):
def func():
call_count[name] += 1
print(f" [调用 {name}() -> {return_value}]")
return return_value
return func
a_true = make_func("a", True)
b = make_func("b", False)
print("a_true() or b():")
call_count = {"a": 0, "b": 0}
result = a_true() or b()
print(f"结果:{result},a 调用次数:{call_count['a']},b 调用次数:{call_count['b']}")
print()
a_false = make_func("a", False)
print("a_false() or b():")
call_count = {"a": 0, "b": 0}
result = a_false() or b()
print(f"结果:{result},a 调用次数:{call_count['a']},b 调用次数:{call_count['b']}")
def test_chained_comparison():
"""测试链式比较"""
print()
print("=" * 60)
print("测试 3:链式比较")
print("=" * 60)
def trace_compare(x, name):
print(f" [比较 x ({name}) = {x}]")
return x
x = 5
print(f"0 < trace_compare(x, 'left') < 10:")
result = 0 < trace_compare(x, "left") < 10
print(f"结果:{result}")
test_short_circuit()
test_or_short_circuit()
test_chained_comparison()
练习二:用户输入验证系统
"""
用户输入验证系统
练习使用逻辑运算符构建复杂验证条件
"""
def validate_user_input(username, age, email, password):
"""验证用户输入"""
errors = []
# 用户名验证
if not username: # 用户名为空
errors.append("用户名不能为空")
elif len(username) < 3:
errors.append("用户名长度不能少于 3 个字符")
elif len(username) > 20:
errors.append("用户名长度不能超过 20 个字符")
elif not username[0].isalpha():
errors.append("用户名必须以字母开头")
# 年龄验证
if not isinstance(age, int):
errors.append("年龄必须是整数")
elif age < 0:
errors.append("年龄不能为负数")
elif age < 18:
errors.append("必须年满 18 岁")
elif age > 150:
errors.append("请输入真实的年龄")
# 邮箱验证
if not email:
errors.append("邮箱不能为空")
elif "@" not in email:
errors.append("邮箱格式不正确")
elif email.count("@") > 1:
errors.append("邮箱格式不正确")
elif "." not in email.split("@")[-1]:
errors.append("邮箱域名格式不正确")
# 密码验证
if not password:
errors.append("密码不能为空")
elif len(password) < 8:
errors.append("密码长度不能少于 8 个字符")
elif len(password) > 128:
errors.append("密码长度不能超过 128 个字符")
elif not any(c.isupper() for c in password):
errors.append("密码必须包含至少一个大写字母")
elif not any(c.islower() for c in password):
errors.append("密码必须包含至少一个小写字母")
elif not any(c.isdigit() for c in password):
errors.append("密码必须包含至少一个数字")
# 综合验证结果
is_valid = len(errors) == 0
return is_valid, errors
# 测试用例
test_cases = [
# (username, age, email, password)
("john", 25, "john@example.com", "Pass1234"),
("jo", 25, "john@example.com", "Pass1234"), # 用户名太短
("john", 15, "john@example.com", "Pass1234"), # 年龄太小
("john", 25, "johnexample.com", "Pass1234"), # 邮箱格式错误
("john", 25, "john@example.com", "pass1234"), # 密码缺少大写字母
]
print("=" * 70)
print("用户输入验证系统测试")
print("=" * 70)
for username, age, email, password in test_cases:
is_valid, errors = validate_user_input(username, age, email, password)
print(f"\n输入:({username!r}, {age}, {email!r}, {password!r})")
if is_valid:
print("结果:✓ 验证通过")
else:
print("结果:✗ 验证失败")
for error in errors:
print(f" - {error}")
练习三:智能配置解析器
"""
智能配置解析器
练习使用短路求值和安全地访问嵌套配置
"""
def get_config_value(config, *keys, default=None):
"""安全地获取嵌套配置值"""
result = config
for key in keys:
# 使用短路求值安全地遍历嵌套字典
result = result and isinstance(result, dict) and result.get(key)
if result is None:
return default
return result if result is not None else default
def parse_config(config):
"""解析配置并返回描述"""
results = []
# 基本设置
app_name = get_config_value(config, "app", "name", default="未命名应用")
version = get_config_value(config, "app", "version", default="0.0.0")
results.append(f"应用:{app_name} v{version}")
# 数据库配置
db_host = get_config_value(config, "database", "host", default="localhost")
db_port = get_config_value(config, "database", "port", default=5432)
db_name = get_config_value(config, "database", "name", default="mydb")
results.append(f"数据库:{db_host}:{db_port}/{db_name}")
# 安全设置
ssl_enabled = get_config_value(config, "security", "ssl", default=False)
ssl_str = "启用" if ssl_enabled else "禁用"
results.append(f"SSL:{ssl_str}")
# 调试模式
debug = get_config_value(config, "app", "debug", default=False)
debug_str = "开启" if debug else "关闭"
results.append(f"调试模式:{debug_str}")
return results
# 测试配置
configs = [
# 完整配置
{
"app": {"name": "MyApp", "version": "1.2.3", "debug": True},
"database": {"host": "db.example.com", "port": 5432, "name": "production"},
"security": {"ssl": True}
},
# 部分配置
{
"app": {"name": "PartialApp"},
"database": {"host": "localhost"}
},
# 空配置
{},
]
for i, config in enumerate(configs, 1):
print(f"=" * 60)
print(f"配置 {i}")
print("=" * 60)
for line in parse_config(config):
print(f" {line}")
print()
常见错误与调试
错误一:混淆 and 与 &
# 错误:使用 and 进行位运算
result = True and False # 逻辑与,结果是 False
# 正确:使用 & 进行位运算
result = True & False # 位与,结果是 False
# 对于整数
a, b = 10, 5
result_and = a and b # 返回 b(5),因为 a 为真
result_bit = a & b # 位与,10 & 5 = 0b1010 & 0b0101 = 0
print(f"a and b = {result_and}")
print(f"a & b = {result_bit}")
错误二:混淆 or 与 |
# 错误:使用 or 进行位运算
result = True or False # 逻辑或,结果是 True
# 正确:使用 | 进行位运算
result = True | False # 位或,结果是 True
# 对于整数
a, b = 10, 5
result_or = a or b # 返回 a(10),因为 a 为真
result_bit = a | b # 位或,10 | 5 = 0b1010 | 0b0101 = 15
print(f"a or b = {result_or}")
print(f"a | b = {result_bit}")
错误三:在布尔上下文中误用字符串
# 错误:使用字符串 "False" 作为布尔值
flag = "False" # 这是一个非空字符串,在布尔上下文中为 True!
if flag:
print("执行了!") # 这会执行,因为 "False" 是真值
# 正确:使用布尔值 False
flag = False
if flag:
print("不会执行")
else:
print("正确:flag 是 False")
错误四:短路求值导致的变量未定义
# 错误:依赖短路求值,但变量在两个分支中都需要
# x = 10
# if x > 0 and y > 0: # NameError: name 'y' is not defined
# pass
# 正确:确保所有变量在使用前已定义
x, y = 10, 5
if x > 0 and y > 0:
print(f"x * y = {x * y}")
错误五:链式比较的误解
# 错误理解:0 < x < 10 表示 x 在 0 到 10 之间
# 但对于非数值类型可能不符合预期
x = "5"
print(f"x = {x!r}")
print(f"0 < x < 10 = {0 < x < 10}") # 对于字符串,"5" 会和数字比较吗?
# 实际上在 Python 3 中这会引发 TypeError
# print(0 < "5" < 10) # TypeError
# 正确:确保链式比较中的变量类型一致
x = 5
print(f"x = {x}, 0 < x < 10 = {0 < x < 10}")
Python 3.11 的特殊行为
None、True、False 的比较
# Python 3.11 中对 None、True、False 的比较优化
# 建议使用 is 进行身份比较,而不是 ==
print("is vs == 对于 None:")
x = None
print(f"x is None = {x is None}") # 推荐
print(f"x == None = {x == None}") # 不推荐
# True 和 False
print(f"True is True = {True is True}")
print(f"False is False = {False is False}")
# 注意:True 和 False 是单例对象
print(f"True is not 1 = {True is not 1}") # True(不同类型)
print(f"True == 1 = {True == 1}") # True(值相等)
本章小结
今天我们学习了以下核心内容:
- 逻辑运算符基础:
and、or、not的基本用法和返回值特性。 - 短路求值机制:
and的短路:当第一个值为假时立即返回or的短路:当第一个值为真时立即返回- 短路求值在安全默认值、避免错误等方面的应用
- 真值测试:Python 中所有对象的布尔值规则,假值和真值列表。
- 链式比较:
0 < x < 10等价于(0 < x) and (x < 10)- Python 只对
x求值一次 - 链式比较的实际应用场景
- 逻辑运算符的优先级:
not > and > or - 高级应用:
- 级联默认值赋值
- 函数存在性检查
- 嵌套字典安全访问
- Python 3.11 改进:布尔运算和比较操作的优化