Python 第五课:逻辑运算符、短路求值与链式比较

课程概述

本节课我们将深入探讨 Python 中三个最重要的逻辑运算符——andornot的工作原理,以及与它们密切相关的短路求值(Short-circuit Evaluation,也称为最小化求值)机制。我们还将详细学习 Python 特有的链式比较(Chained Comparisons)语法,这是 Python 语言中最优雅的特性之一。此外,本课还将涵盖 Python 中所有对象的布尔值规则、真值测试(Truth Value Testing),以及如何利用逻辑运算符的特性编写更加简洁、高效和安全的代码。本课程所有内容基于 Python 3.11 编写,涵盖了 Python 3.11 中关于布尔运算和比较操作的最新实现细节和优化。

逻辑运算符是所有编程语言的基石之一,它们构成了条件判断、循环控制和程序逻辑的核心。Python 的逻辑运算符相比其他语言有一些独特的设计:Python 使用英语单词 andornot 而不是 &&||! 这样的符号,这使得代码更接近自然语言,可读性更强。更重要的是,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 从左到右计算每个表达式。一旦遇到值为假的表达式,就立即返回该值,不再继续计算后续表达式。这是因为只要有一个操作数为 Falseand 的结果就一定是 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 从左到右计算每个表达式。一旦遇到值为真的表达式,就立即返回该值,不再继续计算后续表达式。这是因为只要有一个操作数为 Trueor 的结果就一定是 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(值相等)

本章小结

今天我们学习了以下核心内容:

  1. 逻辑运算符基础andornot 的基本用法和返回值特性。
  2. 短路求值机制
    • and 的短路:当第一个值为假时立即返回
    • or 的短路:当第一个值为真时立即返回
    • 短路求值在安全默认值、避免错误等方面的应用
  3. 真值测试:Python 中所有对象的布尔值规则,假值和真值列表。
  4. 链式比较
    • 0 < x < 10 等价于 (0 < x) and (x < 10)
    • Python 只对 x 求值一次
    • 链式比较的实际应用场景
  5. 逻辑运算符的优先级not > and > or
  6. 高级应用
    • 级联默认值赋值
    • 函数存在性检查
    • 嵌套字典安全访问
  7. Python 3.11 改进:布尔运算和比较操作的优化

延伸阅读