Python逻辑运算符真相:and/or不是布尔开关,而是值传递工具
2026/6/16 4:23:07 网站建设 项目流程

1. 为什么你写的 if 语句总在奇怪的地方出错?——从三个符号开始重学 Python 逻辑运算

你有没有写过这样的代码:if user_age >= 18 and user_status == "active" or is_admin:,测试时发现普通用户也能进后台?或者调试半天,发现if not data_list在空字典{}上居然返回True?又或者把andor连用时,加不加括号结果天差地别,但又说不清到底哪一步先算?这不是你粗心,而是绝大多数人根本没真正“用过”Python 的逻辑运算符——他们只是把and/or/not当成数学课本里的真值表来背,却完全忽略了 Python 赋予它们的行为本质:它们不是返回TrueFalse的“判断开关”,而是返回操作数本身值的短路求值表达式。这个底层机制,直接决定了你在写条件分支、默认值赋值、链式判断甚至函数参数兜底时的成败。本文不讲布尔代数,不列真值表,只带你用真实项目场景(用户权限校验、API 响应处理、配置加载容错)亲手敲代码、看输出、改逻辑,把andornot从“语法符号”变成你手边可拆解、可预测、可复用的工具。无论你是刚学完print("Hello")的新手,还是写了三年 CRUD 却总在if里埋雷的开发者,只要今天能亲手跑通文中的 5 个实操案例,你对 Python 条件逻辑的理解就会跨过一个质变门槛。我们不教“应该怎么做”,只展示“实际发生了什么”,以及“为什么必须这样理解”。

2. 逻辑运算符不是开关,是带刹车的传送带——核心设计思路与底层原理

2.1 为什么 Python 不按套路出牌?从 C/Java 的“纯布尔返回”说起

大多数编程语言(如 C、Java、JavaScript)的逻辑运算符严格遵循布尔代数定义:&&||只返回truefalse。比如在 Java 中,"hello" && 42会直接报错,因为字符串和数字不能参与布尔运算。但 Python 完全不同——它的andor从不强制转换操作数类型,也不制造新布尔值。它们的行为更像一条有智能刹车的传送带:and遇到第一个“假值”就立刻停下,把那个假值传出来;or遇到第一个“真值”就立刻停下,把那个真值传出来;如果一路走到底,就传最后一个操作数。这个设计源于 Python 的哲学:“实用优先,显式优于隐式”。它让逻辑运算符天然支持短路求值(short-circuit evaluation)值传递(value propagation),从而衍生出远超条件判断的实用场景。

提示:Python 中的“假值”(falsy)只有 7 个:None,False,0,0.0,0j, 空序列('',[],()), 空映射({})。除此之外,一切皆为“真值”(truthy)。注意:0是假值,但'0'(字符串零)是真值;[]是假值,但[None]是真值。这个列表必须刻进本能,否则所有逻辑都会错乱。

2.2and的真实行为:找第一个“拦路虎”,不是找“假”

我们常误以为a and b是“当 a 为真时返回 b”。这是结果,不是过程。真实过程是:从左到右依次求值 a 和 b,一旦遇到第一个假值,立即返回它;如果 a 为真,则必须计算 b,并返回 b(无论 b 是真是假)。来看几个颠覆认知的例子:

# 案例1:a 是假值,直接返回 a,b 根本不执行! result = [] and print("This will NOT be printed") print(repr(result)) # 输出:[] —— print() 函数压根没被调用! # 案例2:a 是真值,必须计算 b,返回 b 的值(哪怕 b 是假值) result = [1, 2] and {} print(repr(result)) # 输出:{} —— 返回的是空字典本身,不是 True/False # 案例3:多操作数链式,找第一个假值 result = "first" and 100 and [] and "never reached" print(repr(result)) # 输出:[] —— 在第三个操作数 [] 处停下,返回它

这个“拦路虎”机制意味着and安全的前置检查工具。例如,在访问嵌套字典前,你可以写data and data.get('user') and data['user'].get('profile'),只要datadata['user']为假(如None或空),整个链式表达式就会在那一步停下并返回假值,不会触发KeyError。这比写一长串if判断简洁得多,且完全依赖and的短路特性。

2.3or的真实行为:找第一个“通行证”,不是找“真”

同理,a or b的过程是:从左到右依次求值 a 和 b,一旦遇到第一个真值,立即返回它;如果 a 为假,则必须计算 b,并返回 b(无论 b 是真是假)。关键点在于:or返回的是“第一个真值”,而不是True。这直接催生了 Python 最经典的默认值模式:

# 案例1:a 是假值,计算并返回 b name = "" or "Anonymous" print(name) # 输出:"Anonymous" # 案例2:a 是真值,直接返回 a,b 不执行 name = "Alice" or expensive_function() print(name) # 输出:"Alice" —— expensive_function() 根本没运行! # 案例3:多操作数,找第一个真值 config = None or {} or {"host": "localhost", "port": 8000} print(config) # 输出:{'host': 'localhost', 'port': 8000} # 案例4:陷阱!如果所有操作数都是假值,返回最后一个! result = [] or {} or 0 print(repr(result)) # 输出:0 —— 不是 False!

这个“通行证”机制让or成为优雅的兜底方案。它不关心你给的默认值是什么类型,只要它是真值(或你接受它作为最终返回值),它就工作。这也是为什么or常用于函数参数默认值:def connect(host=None): host = host or "localhost"。但请注意:如果host可能是0(比如端口号为 0),这种写法会出错,因为0是假值,会被"localhost"替换——此时必须用is None显式判断。

2.4not:唯一真正的布尔转换器,但用法极简

not是三者中唯一严格返回TrueFalse的运算符。它的行为简单:not x先对x求布尔值(bool(x)),然后取反。但它不改变x本身的值,只产生一个新布尔对象。因此,not的核心用途只有一个:生成明确的布尔条件,用于ifwhile等需要真/假判断的上下文

# not 的本质:bool() + 取反 print(not []) # True (bool([]) 是 False,取反为 True) print(not [1]) # False (bool([1]) 是 True,取反为 False) print(not None) # True print(not 0) # True print(not "0") # False ('0' 是真值) # 关键区别:not 返回布尔值,and/or 返回原值 data = [] print(type(data and "fallback")) # <class 'list'> —— 返回原 list 对象 print(type(not data)) # <class 'bool'> —— 返回新 bool 对象

正因为not只返回布尔值,它绝不能用于获取默认值或做值传递。试图写name = not user_name or "Anonymous"是严重错误:如果user_name"Bob"not "Bob"FalseFalse or "Anonymous""Anonymous",结果永远是默认值!正确写法永远是user_name or "Anonymous"

3. 实操拆解:5 个真实场景,亲手验证逻辑运算符的“行为艺术”

3.1 场景一:用户登录状态校验——用and构建安全的权限链

假设你有一个 Web 应用,需要检查用户是否已登录、是否为活跃状态、是否拥有管理员权限,才能进入管理后台。传统写法是嵌套if

# 传统写法(冗长且易漏) if user: if user.is_active: if user.is_admin: grant_access() else: deny_access("Insufficient permissions") else: deny_access("Account inactive") else: deny_access("Not logged in")

and的短路特性,可以将其压缩为一行清晰、安全的表达式:

# 实操代码:安全权限链 def check_admin_access(user): # 步骤1:模拟用户对象(可能为 None) # 步骤2:利用 and 的短路,任何环节为假则整条链返回该假值 result = ( user and # 如果 user 为 None/False,直接返回它,后续不执行 user.is_active and # user 存在才检查 is_active(避免 AttributeError) user.is_admin # user 存在且活跃才检查 is_admin ) # 步骤3:result 是什么?是 user 对象、False、None,还是 True? # 我们需要一个明确的布尔结果用于 if 判断 is_authorized = bool(result) # 将结果统一转为布尔值 print(f"user: {user}, result: {repr(result)}, is_authorized: {is_authorized}") return is_authorized # 测试用例 print("=== 测试1:正常管理员用户 ===") class User: def __init__(self, is_active, is_admin): self.is_active = is_active self.is_admin = is_admin admin_user = User(True, True) check_admin_access(admin_user) # result: True, is_authorized: True print("\n=== 测试2:用户对象为 None ===") check_admin_access(None) # result: None, is_authorized: False (user 为 None,and 链在第一步停下) print("\n=== 测试3:用户存在但不活跃 ===") inactive_user = User(False, True) check_admin_access(inactive_user) # result: False, is_authorized: False (is_active 为 False,and 链在第二步停下) print("\n=== 测试4:用户活跃但非管理员 ===") regular_user = User(True, False) check_admin_access(regular_user) # result: False, is_authorized: False (is_admin 为 False,and 链在第三步停下)

实操心得:这个模式的核心价值在于自动规避属性访问异常。你不需要写if hasattr(user, 'is_active')try/exceptand的短路天然保证:只有前一个操作数为真时,才会去求值下一个。这极大简化了防御性编程。但务必记住:result是原始值(None,False,True),如果后续逻辑需要布尔值,必须显式bool(result)。直接if result:result0[]时也会失败,所以bool()是安全转换的黄金法则。

3.2 场景二:API 响应数据提取——用or实现多级默认值兜底

调用第三方 API 时,响应结构可能不稳定:字段可能缺失、值可能为空、嵌套层级可能变化。用or链可以优雅地提供逐级默认值:

# 实操代码:API 响应兜底 def extract_user_info(api_response): # 模拟不稳定的 API 响应 # 理想情况:{"data": {"user": {"name": "Alice", "email": "a@b.com"}}} # 可能情况1:{"error": "timeout"} -> data 不存在 # 可能情况2:{"data": {}} -> user 不存在 # 可能情况3:{"data": {"user": {}}} -> name/email 不存在 # 步骤1:获取 data 字段,如果不存在或为 None/空,用空字典兜底 data = api_response.get("data") or {} # 步骤2:从 data 中获取 user 字段,如果不存在或为 None/空,用空字典兜底 user = data.get("user") or {} # 步骤3:从 user 中获取 name,如果不存在或为空字符串,用默认名 # 注意:这里用 '' or "Unknown",因为空字符串是假值 name = user.get("name") or "Unknown" # 步骤4:从 user 中获取 email,如果不存在或为空字符串,用默认邮箱 email = user.get("email") or "no-email@example.com" # 步骤5:组合结果(注意:这里用 or 是为了确保 name/email 是字符串,不是 None) result = { "name": name, "email": email, "raw_data": api_response # 保留原始响应用于调试 } print(f"API Response: {api_response}") print(f"Extracted: {result}") return result # 测试用例 print("=== 测试1:完整响应 ===") full_response = {"data": {"user": {"name": "Bob", "email": "bob@site.com"}}} extract_user_info(full_response) print("\n=== 测试2:data 字段缺失 ===") missing_data = {"error": "Service unavailable"} extract_user_info(missing_data) # data = {} (空字典), user = {}, name="Unknown", email="no-email..." print("\n=== 测试3:user 字段为空字典 ===") empty_user = {"data": {}} extract_user_info(empty_user) # user = {}, name="Unknown", email="no-email..." print("\n=== 测试4:name 为空字符串 ===") empty_name = {"data": {"user": {"name": "", "email": "valid@em.com"}}} extract_user_info(empty_name) # name = "" or "Unknown" -> "Unknown"

实操心得or链在这里扮演了“降级策略”的角色。每一层or都是一个安全网,确保即使上游数据崩塌,下游逻辑依然能拿到一个可用的、类型一致的值(这里是字典或字符串)。但要警惕一个经典陷阱:数字0是假值。如果 API 可能返回{"count": 0},而你写response.get("count") or 1,那么0会被错误地替换为1。此时必须用显式判断:response.get("count", 0)dict.get的第二个参数是默认值,不经过布尔判断)或0 if response.get("count") is None else response["count"]or只适用于你明确希望将所有假值都视为“缺失”并替换的场景。

3.3 场景三:配置文件加载容错——混合andor构建鲁棒初始化

应用启动时,需要从环境变量、配置文件、硬编码默认值三个来源加载配置。顺序是:环境变量 > 配置文件 > 默认值。且每个来源都可能失效(环境变量未设置、配置文件读取失败、解析出错)。用andor可以构建一个无try/except的单行初始化:

# 实操代码:鲁棒配置加载 import os import json def load_config(): # 模拟三个配置源 # 1. 环境变量(可能未设置) env_config_str = os.environ.get("APP_CONFIG") # 2. 配置文件(可能不存在或损坏) config_file_path = "config.json" file_config_str = None try: with open(config_file_path, "r") as f: file_config_str = f.read() except (FileNotFoundError, PermissionError, OSError): pass # 文件不可用,file_config_str 保持 None # 3. 硬编码默认值(总是可用) default_config_str = '{"debug": false, "timeout": 30}' # 步骤1:尝试解析环境变量配置(如果存在且解析成功,则使用它) # 解析函数:成功返回 dict,失败返回 None def safe_json_load(s): try: return json.loads(s) if s else None except (json.JSONDecodeError, TypeError): return None # 步骤2:构建加载链 # 优先级:env -> file -> default # 逻辑:先尝试 env,如果失败(返回 None 或解析出错),再试 file;如果 file 也失败,最后用 default # 关键:用 and 确保每一步都“成功”(即返回非 None 的 dict),用 or 进行兜底 config = ( safe_json_load(env_config_str) or # 如果 env 解析成功,返回 dict;失败返回 None safe_json_load(file_config_str) or # 如果 env 失败,尝试 file;失败返回 None json.loads(default_config_str) # 如果前两者都失败,硬编码默认值(总是成功) ) print(f"Env var APP_CONFIG: {env_config_str}") print(f"Config file '{config_file_path}' content: {file_config_str}") print(f"Loaded config: {config}") return config # 测试用例(需手动设置环境变量或创建文件,此处模拟) print("=== 测试1:环境变量有效 ===") os.environ["APP_CONFIG"] = '{"debug": true, "timeout": 60}' load_config() # 应输出 env 的配置 print("\n=== 测试2:环境变量无效,配置文件有效 ===") os.environ.pop("APP_CONFIG", None) # 清除环境变量 # 模拟文件内容 with open("config.json", "w") as f: f.write('{"debug": false, "timeout": 45}') load_config() # 应输出文件的配置 print("\n=== 测试3:所有外部源失败,回退到默认值 ===") os.environ.pop("APP_CONFIG", None) import os try: os.remove("config.json") except FileNotFoundError: pass load_config() # 应输出硬编码默认值

实操心得:这个例子展示了andor的协同威力。or负责在多个“候选源”之间做选择(A 或 B 或 C),而and(隐含在safe_json_load的内部逻辑中)确保每个候选源的“质量”——只有解析成功(返回非 None dict)才算“合格”。整个链式结构清晰表达了业务优先级,且没有一行iftry/except。但要注意:or链的每个环节必须是等价类型(这里都是dictNone),否则or返回的类型会混乱。如果default_config_str是字符串而非dictor链最后会返回字符串,导致config类型错误。因此,or链的终点必须是“终极兜底”,其类型必须与前面所有环节的期望返回类型一致。

3.4 场景四:函数参数默认值与空值处理——or的边界与is None的救赎

很多教程教初学者用def func(name="Unknown"):,但当参数可能传入0""[]等假值时,or就成了陷阱。我们必须学会何时用or,何时用is None

# 实操代码:参数默认值的两种范式 def process_order_v1(quantity=1): """错误示范:用 or 处理可能为 0 的参数""" # 这里 quantity 可能是 0(表示取消订单),但 or 会把它当成“缺失” actual_quantity = quantity or 1 print(f"V1 - Requested: {quantity}, Actual: {actual_quantity}") def process_order_v2(quantity=None): """正确示范:用 is None 显式区分“未传参”和“传了假值”""" # 只有 quantity 是 None 时,才用默认值;如果是 0、""、[],就照单全收 actual_quantity = quantity if quantity is not None else 1 print(f"V2 - Requested: {quantity}, Actual: {actual_quantity}") def process_order_v3(quantity=None): """Pythonic 写法:用 or 仅当默认值是字符串/列表等,且假值确实代表“缺失”""" # 例如,用户名参数:None 或 "" 都应视为未提供,用默认名 username = quantity or "Guest" # 这里 quantity 是 str 类型 print(f"V3 - Username: {quantity} -> {username}") # 测试对比 print("=== V1:用 or 处理数字(错误)===") process_order_v1(0) # 输出:Requested: 0, Actual: 1 (错误!0 被误认为缺失) process_order_v1(5) # 输出:Requested: 5, Actual: 5 process_order_v1(None) # TypeError! 因为 None 不能和 1 进行 or 运算(None 是假值,但 or 需要操作数) print("\n=== V2:用 is None 处理数字(正确)===") process_order_v2(0) # 输出:Requested: 0, Actual: 0 (正确!0 被接受) process_order_v2(5) # 输出:Requested: 5, Actual: 5 process_order_v2(None) # 输出:Requested: None, Actual: 1 (正确!None 才触发默认) print("\n=== V3:用 or 处理字符串(合理)===") process_order_v3("") # 输出:Username: -> Guest (空字符串视为缺失) process_order_v3("Alice") # 输出:Username: Alice -> Alice process_order_v3(None) # 输出:Username: None -> Guest (None 也视为缺失)

实操心得:这是最常踩的坑。or的适用场景是:你希望将所有“假值”都视为“未提供”或“无效”,并统一替换为默认值。这在处理字符串("")、列表([])、字典({})等容器类型时非常自然。但对数字(0,0.0)、甚至布尔值(False),or就会混淆语义。此时,is None是唯一安全的选择,因为它只检查“是否为 None”,不进行任何布尔转换。记住口诀:“容器用 or,数字用 is None”。另外,or在函数定义中无法直接使用(如def f(x=0 or 1)是语法错误),它只能在函数体内作为表达式使用。

3.5 场景五:条件表达式(三元运算符)与逻辑运算符的共生关系

Python 的三元运算符x if condition else y与逻辑运算符高度互补。它们可以组合出极其精炼的逻辑:

# 实操代码:三元运算符与逻辑运算符的组合 def get_user_role_v1(user): """用 and/or 模拟三元运算符(不推荐,难读)""" # 目标:如果 user 是管理员,返回 "admin";否则如果 user 是普通用户,返回 "user";否则返回 "guest" # 错误写法(极易出错): # role = (user.is_admin and "admin") or (user.is_active and "user") or "guest" # 问题:如果 user.is_admin 是 True,返回 "admin";但如果 user.is_admin 是 False,整个左边是 False, # 然后计算右边 (user.is_active and "user"),如果 user.is_active 是 True,返回 "user";但如果 user.is_active 是 False, # 整个右边是 False,最后返回 "guest"。看起来没问题?但等等... # 如果 user.is_admin 是 False,user.is_active 是 True,user.is_active and "user" 是 "user"(真值),没问题。 # 但如果 user.is_admin 是 False,user.is_active 是 False,user.is_active and "user" 是 False(假值),然后 or "guest" 返回 "guest"。OK。 # 但问题在于:如果 user.is_admin 是 True,但 "admin" 是空字符串 ""(假值)?不可能,"admin" 是真值。 # 所以这个写法在字符串上是安全的,但极度脆弱。 pass def get_user_role_v2(user): """用三元运算符(推荐,清晰)""" # 清晰、可读、无歧义 if user.is_admin: return "admin" elif user.is_active: return "user" else: return "guest" def get_user_role_v3(user): """用嵌套三元运算符(极简,需谨慎)""" # 一行解决,但可读性下降 return "admin" if user.is_admin else ("user" if user.is_active else "guest") def get_user_role_v4(user): """用 and/or 的正确姿势:只用于二选一,且值为真值""" # 当且仅当两个分支都返回真值(非空字符串、非零数字等)时,and/or 才安全 # 例如:获取用户的显示名称,优先用昵称,没有则用用户名 display_name = user.nickname and user.nickname or user.username # 分析:如果 nickname 为真,返回 nickname;如果 nickname 为假,返回 username(无论 username 是真是假) # 这等价于:nickname if nickname else username return display_name # 测试 class MockUser: def __init__(self, is_admin, is_active, nickname, username): self.is_admin = is_admin self.is_active = is_active self.nickname = nickname self.username = username print("=== V2:标准 if-elif-else(最推荐)===") admin = MockUser(True, True, "Boss", "admin123") print(f"Admin user: {get_user_role_v2(admin)}") # admin regular = MockUser(False, True, "Player", "user456") print(f"Regular user: {get_user_role_v2(regular)}") # user guest = MockUser(False, False, "", "guest789") print(f"Guest user: {get_user_role_v2(guest)}") # guest print("\n=== V4:and/or 用于二选一(安全场景)===") user_with_nick = MockUser(False, True, "Gamer", "user456") print(f"With nickname: {get_user_role_v4(user_with_nick)}") # Gamer user_no_nick = MockUser(False, True, "", "user456") print(f"Without nickname: {get_user_role_v4(user_no_nick)}") # user456

实操心得and/or组合模拟三元运算符(a and b or c)是一个广为流传但强烈不推荐的技巧。它的逻辑是:(a and b)如果为真,整个表达式就是b;如果(a and b)为假(即a为假,或a为真但b为假),则计算c。问题在于,当b本身是假值(如b="")时,即使a为真,整个表达式也会错误地返回c。因此,永远优先使用x if condition else yand/or只应在bc都是确定的真值(如非空字符串、非零数字、非空列表)时,作为b if a else c的极简替代,且必须确保b不可能为假值。在生产代码中,清晰胜于简洁,if-else是绝对首选。

4. 常见问题与排查技巧实录:那些让你熬夜调试的“逻辑幽灵”

4.1 问题速查表:典型症状、根本原因与修复方案

症状(Symptom)根本原因(Root Cause)修复方案(Fix)实操验证代码
if user and user.profile.name:AttributeError: 'NoneType' object has no attribute 'profile'user是真值(如User对象),但user.profileNoneand链继续执行到user.profile.name时失败and链中加入对中间对象的显式检查:user and user.profile and user.profile.nameuser = User(); user.profile = None; result = user and user.profile and user.profile.nameresultNone,无异常
config = os.environ.get("DB_URL") or "sqlite:///default.db"导致数据库连接到sqlite:///default.db,而实际环境变量DB_URL的值是"postgres://..."os.environ.get("DB_URL")返回的是字符串,但字符串可能为空""(假值),or将其替换为默认值使用os.environ.get("DB_URL", "sqlite:///default.db")dict.get的第二个参数是默认值,不经过布尔判断os.environ["DB_URL"] = ""; config = os.environ.get("DB_URL") or "sqlite:///default.db""sqlite:///default.db"config2 = os.environ.get("DB_URL", "sqlite:///default.db")""
data = request.json and request.json.get("items") or []总是返回[],即使request.jsonitems字段request.json.get("items")返回[](空列表,假值),and链的结果是[][] or []还是[],逻辑被破坏or移到最外层,确保and链只负责安全访问:data = (request.json and request.json.get("items")) or []request = type('obj', (), {})(); request.json = {"items": [1,2,3]}; data = request.json and request.json.get("items") or [][1,2,3]request.json = {"items": []}; data = (request.json and request.json.get("items")) or [][]
if not user.is_active:user.is_active是字符串"false"时,意外进入ifnot "false"False(因为非空字符串是真值),但开发者误以为"false"字符串应被视为逻辑假在比较前,先将字符串标准化为布尔值:is_active = user.is_active.lower() in ("true", "1", "yes", "on"),再if not is_active:user = type('obj', (), {})(); user.is_active = "false"; print(not user.is_active)Falseis_active = user.is_active.lower() in ("true", "1"); print(not is_active)True
result = a or b or c返回0,但预期是TrueFalseor返回的是操作数本身,0是假值,但它是整数0,不是布尔False如果需要布尔结果,显式转换:bool(a or b or c)a, b, c = [], {}, 0; result = a or b or c; print(result, type(result), bool(result))0 <class 'int'> False

4.2 排查技巧:如何一眼看穿逻辑表达式的执行路径?

当你面对一个复杂的and/or链并感到困惑时,不要猜,用这个三步法现场“解剖”:

  1. 列出所有操作数及其真假性:把链式表达式拆开,对每个操作数单独调用bool(),记录结果。
  2. 模拟短路过程:从左到右,根据and(遇假即停)或or(遇真即停)的规则,标记出哪个操作数是“命中点”。
  3. 确认返回值:命中点的操作数值,就是整个表达式的返回值。
# 实操演示:解剖复杂表达式 expr = "a and b or c and d" # 假设:a=True, b=[], c={}, d="hello" # 步骤1:列出真假性 print(f"bool(a)=True, bool(b)={bool([])}, bool(c)={bool({})}, bool(d)={bool('hello')}") # 输出:bool(a)=True, bool(b)=False, bool(c)=False, bool(d)=True # 步骤2:模拟执行 # a and b:a 为 True,必须计算 b;b=[] 是 False,所以 a and b 返回 [] # [] or c:[] 是 False,必须计算 c;c={} 是 False,所以 [] or c 返回 {} # {} and d:{} 是 False,所以 {} and d 返回 {} # 步骤3:最终结果是 {} result = True and [] or {} and "hello" print(f"Expression: {expr}") print(f"Result: {repr(result)}") # 输出:{} # 验证:加括号强制优先级 # (a and b) or (c and d) -> ([] or ({} and "hello")) -> ([] or {}) -> {} # a and (b or c) and d -> True and ({} or "hello") and "hello" -> True and "hello" and "hello" -> "hello" # 结论:原表达式等价于 ((a and b) or c) and d?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询