第 3 章 运算符与表达式

782 阅读12分钟

在 Python 中,运算符与表达式是实现计算逻辑与数据处理的基础。运算符定义数据间的操作规则,表达式则通过运算符与操作数的组合形成可执行的计算单元。从数值计算到条件判断,从数据过滤到逻辑推理,它们贯穿程序实现的全过程。本章系统阐述 Python 运算符的分类、特性及规则,结合工程实践解析表达式构建技巧,帮助读者建立清晰的计算逻辑框架,为编写高效可读的代码奠定基础。

3.1 算术运算符

算术运算符是处理数值计算的基础工具,不仅支持常规的数学运算,还针对编程场景扩展了特殊功能(如字符串重复、整除运算)。掌握其运算规则与适用场景,是实现数值处理逻辑的前提。

3.1.1 基本算术运算符

Python 支持的基础算术运算符如下(假设a = 10, b = 3):

运算符含义示例结果说明
+加法a + b13结果类型随操作数变化(如2 + 3.0 → 5.0
-减法a - b7用于差值计算,如age - 18
*乘法a * b30支持字符串重复:"hi" * 3 → "hihihi"
/除法a / b3.3333始终返回浮点数(6 / 2 → 3.0
//整除a // b3返回整数商,浮点数运算结果为浮点型(7.0 // 2 → 3.0
%取余a % b1用于奇偶判定、周期计算(如day % 7取星期几)
**幂运算a** b1000乘方计算,如4 **0.5 → 2.0(开平方)

示例:基础算术运算

# 场景:商品价格计算
price: float = 99.9
quantity: int = 3
total: float = price * quantity  # 乘法运算
average: float = total / quantity  # 除法运算(结果为浮点数)
discount: float = total // 10  # 整除运算(抹零处理)print(f"总价:{total},均价:{average},折扣后:{discount}")
# 输出:总价:299.7,均价:99.9,折扣后:29.0

3.1.2 运算优先级与求值顺序

算术运算符的优先级遵循数学规则,可通过括号调整执行顺序:

  1. 幂运算 **
  2. 乘、除、整除、取余 * / // %
  3. 加、减 + -

示例:优先级与括号的影响

result1: int = 2 + 3 * 4      # 14(先乘后加)
result2: int = (2 + 3) * 4    # 20(括号改变优先级)

此外,Python 表达式的求值顺序通常为从左到右(赋值运算符除外),但幂运算特殊,遵循从右到左的规则:

print(8 / 4 / 2)  # 1.0(等价于(8/4)/2,从左到右)
print(2** 3 **2)  # 64(等价于2** (3 **2),从右到左)

3.1.3 复合赋值运算符

复合赋值是 “运算 + 赋值” 的简写形式,常用于循环计数、数值累计等场景,简化代码的同时保持可读性。

常用复合赋值运算符+=(加赋值)、-=(减赋值)、*=(乘赋值)、/=(除赋值)、//=(整除赋值)、%=(取余赋值)、**=(幂赋值)。

示例:复合赋值的应用

# 场景:订单金额累计
total_amount: float = 0.0
order_prices: list[float] = [99.9, 199.9, 299.9]
​
for price in order_prices:
    total_amount += price  # 等价于 total_amount = total_amount + priceprint(f"累计金额:{total_amount:.2f}")  # 输出:累计金额:599.70

3.1.4 位运算符

位运算符用于对整数的二进制位进行直接操作,在底层编程、状态压缩、算法优化等场景中广泛应用。虽然日常开发中使用频率较低,但仍是运算符体系的重要组成部分。

常用位运算符(假设a = 60b110b = 30b011):

运算符含义示例结果(二进制)结果(十进制)
&按位与a & b0b0102
``按位或`ab`0b1117
^按位异或a ^ b0b1015
~按位取反~a0b...11111001-7
<<左移(乘 2ⁿ)a << 10b110012
>>右移(除 2ⁿ)a >> 10b113

示例:位运算的实际应用

# 场景1:状态压缩(用二进制位表示多个开关状态)
# 定义状态位:bit0=灯光(1=开),bit1=空调(1=开),bit2=电视(1=开)
status: int = 0b101  # 二进制101 → 灯光开、空调关、电视开# 检查灯光是否开启(判断bit0是否为1)
is_light_on: bool = (status & 0b001) != 0
print(f"灯光状态:{is_light_on}")  # 输出:灯光状态:True# 打开空调(设置bit1为1)
status |= 0b010
print(f"更新后状态(二进制):{bin(status)}")  # 输出:0b111
​
​
# 场景2:高效计算(左移1位等价于乘2,右移1位等价于整除2)
num: int = 10
print(num << 1)  # 20(10 × 2¹)
print(num >> 1)  # 5(10 ÷ 2¹,整除)

📌 重点提示:位运算直接操作二进制位,效率远高于算术运算,适合对性能要求高的场景(如高频交易、算法竞赛)。但可读性较低,非必要场景建议优先使用算术运算符。

3.2 比较运算符

比较运算符用于判断两个值之间的关系,返回布尔值True(真)或False(假),是条件判断、分支控制的核心工具。

3.2.1 基本比较运算符

假设a = 10, b = 3,常用比较运算符如下:

运算符含义示例结果说明
==等于a == bFalse判断值是否相等;字符串区分大小写("A" == "a" → False
!=不等于a != bTrue判断值是否不同
>大于a > bTrue用于数值大小比较
<小于a < bFalse与大于相反
>=大于等于a >= bTrue包含等于情况
<=小于等于a <= bFalse包含等于情况

示例:比较运算的应用

# 场景:用户年龄与分数判断
age: int = 20
score: float = 85.5
​
is_adult: bool = age >= 18  # 是否成年
is_excellent: bool = score > 90  # 是否优秀print(f"成年:{is_adult},优秀:{is_excellent}")  # 输出:成年:True,优秀:False

3.2.2 链式比较与类型限制

Python 支持链式比较,即用一个表达式表示多个条件的组合,等价于用and连接多个比较,简洁直观:

# 场景:判断数值是否在区间内
x: int = 5
print(1 < x < 10)      # True(等价于 1 < x and x < 10)
​
age: int = 20
print(18 <= age <= 25) # True(判断是否为18-25岁区间)

📌 重点提示:Python 3 严格限制跨类型比较,不同类型(如intstr)直接比较会报错,避免隐式转换导致的歧义:

print(10 > "5")  # 报错:TypeError(int与str无法比较)

3.3 逻辑运算符

逻辑运算符用于连接多个条件表达式,构建复合逻辑判断,包括and(与)、or(或)、not(非)三种基本运算。

3.3.1 逻辑运算符的基本用法

运算符含义示例结果说明
and与(且)True and FalseFalse所有条件均为真才返回真
orTrue or FalseTrue任一条件为真即返回真
not非(取反)not TrueFalse对条件结果取反

示例:复合条件判断

# 场景:判断用户是否满足活动参与条件
has_ticket: bool = True
is_vip: bool = False
age: int = 22# 条件:有票 且 (是VIP 或 年龄≥18)
can_join: bool = has_ticket and (is_vip or age >= 18)
print(f"能否参与活动:{can_join}")  # 输出:能否参与活动:True

3.3.2 逻辑运算的短路特性

Python 逻辑运算具有短路特性

  • A and B:若A为假,直接返回A,不再计算B
  • A or B:若A为真,直接返回A,不再计算B

示例:短路逻辑的应用

def check() -> bool:
    print("执行检查")
    return Trueprint(False and check())  # 输出:False(A为假,不执行check())
print(True or check())   # 输出:True(A为真,不执行check())

此外,逻辑运算符并非仅返回True/False,而是返回实际参与运算的 “真值” 或 “假值”(Python 中所有数据都有真假性):

  • 假值:00.0None、空字符串""、空列表[]、空字典{}等;
  • 真值:非假值的所有数据(如非零数值、非空字符串、非空集合等)。

示例:非布尔返回值的应用

# 场景:设置默认值(若config为空则用默认值)
config: dict = {}  # 空字典(假值)
default_config: dict = {"mode": "auto"}
​
active_config = config or default_config
print(active_config)  # 输出:{'mode': 'auto'}(取第一个真值)

📌 重点提示:利用or设置默认值、and实现 “条件执行” 是 Python 常见技巧,但需确保代码可读性,避免过度使用导致逻辑模糊。

3.4 成员运算符与身份运算符

成员运算符用于判断元素与集合的归属关系,身份运算符用于判断变量是否指向同一对象,二者在数据校验、对象管理场景中频繁使用。

3.4.1 成员运算符

成员运算符包括in(元素在集合中)和not in(元素不在集合中),支持字符串、列表、元组、字典、集合等多种序列类型。

示例:成员运算的应用

# 场景1:检查用户权限
user_roles: list[str] = ["editor", "viewer"]
is_admin: bool = "admin" in user_roles
print(f"是否为管理员:{is_admin}")  # 输出:是否为管理员:False
​
​
# 场景2:检查字符串包含关系
message: str = "I love Python programming"
has_keyword: bool = "Python" in message
print(f"包含关键词:{has_keyword}")  # 输出:包含关键词:True
​
​
# 场景3:检查字典键存在(字典的in仅判断键,不判断值)
user: dict[str, int] = {"id": 1001, "age": 22}
has_email: bool = "email" in user
print(f"包含邮箱字段:{has_email}")  # 输出:包含邮箱字段:False

📌 性能提示:集合(set)的in操作效率(时间复杂度O(1))远高于列表(O(n)),对需频繁判断归属的场景,建议先将列表转为集合:

# 高效:用集合存储高频查询的元素
valid_ids: set[int] = {1001, 1002, 1003}
print(1002 in valid_ids)  # 快速判断

3.4.2 身份运算符

身份运算符包括is(指向同一对象)和is not(指向不同对象),用于判断变量的引用关系,与==(值相等)有本质区别:

  • ==:判断两个对象的值是否相等;
  • is:判断两个变量是否指向内存中的同一对象。

示例:身份运算与值比较的区别

a: list[int] = [1, 2, 3]
b: list[int] = a  # b与a指向同一列表
c: list[int] = [1, 2, 3]  # c是新列表(值与a相等但对象不同)print(a == b)  # True(值相等)
print(a == c)  # True(值相等)
print(a is b)  # True(同一对象)
print(a is c)  # False(不同对象)

小整数池机制:Python 对-5~256的整数会复用对象(小整数池),导致看似独立的变量可能指向同一对象,这是身份运算的特殊场景:

x: int = 100
y: int = 100
print(x is y)  # True(小整数池复用对象)
​
x_large: int = 1000
y_large: int = 1000
print(x_large is y_large)  # False(大整数不复用)

📌 最佳实践:判断None时必须使用is None(而非== None),这是 Python 社区的规范:

value = None
print(value is None)  # 推荐:True
print(value == None)  # 不推荐:True(语法合法但不符合规范)

3.5 表达式综合应用与工程实践

表达式是编程逻辑的载体,合理使用运算符特性、优化表达式结构,对代码的可读性与执行效率至关重要。

3.5.1 多变量赋值与解包

Python 支持多变量并行赋值,可一次性为多个变量分配值,常用于数据解包、变量交换等场景:

# 场景1:并行赋值(变量数与值数必须一致)
name, age, is_student = "Alice", 20, True
print(f"姓名:{name},年龄:{age}")  # 输出:姓名:Alice,年龄:20
​
​
# 场景2:变量交换(无需临时变量)
a, b = 10, 20
a, b = b, a  # 交换a和b的值
print(f"a={a}, b={b}")  # 输出:a=20, b=10
​
​
# 场景3:可迭代对象解包(提取结构化数据)
user_info: tuple = ("Bob", 22, "bob@example.com")
name, age, email = user_info  # 元组解包
print(f"邮箱:{email}")  # 输出:邮箱:bob@example.com

3.5.2 海象运算符(:=

Python 3.8 引入的海象运算符:=)允许在表达式中同时完成赋值与判断,简化代码结构,尤其适合在条件判断中复用计算结果:

# 传统写法:需计算两次len(list)
user_list: list = ["Alice", "Bob", "Charlie"]
if len(user_list) > 2:
    print(f"列表过长({len(user_list)}个元素)")
​
​
# 海象运算符写法:一次计算,多次使用
if (count := len(user_list)) > 2:
    print(f"列表过长({count}个元素)")  # 输出:列表过长(3个元素)

适用场景

  • 条件判断中需要复用计算结果;
  • 循环中控制迭代条件;
  • 列表推导式中简化逻辑。

📌 使用原则:海象运算符虽能简化代码,但过度使用会降低可读性,仅在 “一次计算多次使用” 的明确场景中使用。

3.5.3 表达式的编程实践

1.** 拆分复杂表达式 ** 冗长的表达式会降低可读性,应拆分为语义化变量,使逻辑更清晰:

# 不推荐:复杂表达式难以理解
if (user.age > 18 and user.is_active and (user.balance > 1000 or user.vip)):
    print("允许访问")
​
# 推荐:拆分后逻辑明确
is_adult: bool = user.age > 18
is_active: bool = user.is_active
has_privilege: bool = user.balance > 1000 or user.vip
if is_adult and is_active and has_privilege:
    print("允许访问")
  1. 明确运算优先级即使运算符有默认优先级,对复杂表达式仍建议用括号明确执行顺序,避免歧义:

    result: float = 2 + 3 * (4 **2)  # 推荐:用括号明确优先级
    # 等价于 2 + (3 * (4** 2)),结果为 50
    
  2. 避免隐蔽的类型转换逻辑运算的非布尔返回值可能导致意外结果,需确保条件判断的意图清晰:

    # 风险:0是假值,但可能被误判为“不存在”
    count: int = 0
    if count:  # 等价于 if count != 0
        print("有数据")
    else:
        print("无数据")  # 输出:无数据(正确)# 更安全:明确判断
    if count > 0:
        print("有数据")
    
  3. 优先使用 Python 特色语法利用链式比较、成员运算等特性简化代码,符合 Python 社区的 “简洁优雅” 原则:

    # 不推荐:冗余的条件判断
    if score >= 60 and score <= 100:
        print("成绩有效")
    ​
    # 推荐:链式比较更简洁
    if 60 <= score <= 100:
        print("成绩有效")