Skip to content

02-运算符

本章代码基于 Python 3.11+ 编写

运算符是程序进行计算和判断的基础,掌握运算符让程序能够处理数据。


本章讲解 Python 的算术运算符、比较运算符和逻辑运算符。


概念铺垫

为什么需要运算符?一个真实的计算场景

问题场景: 你在开发一个购物计算程序,需要计算总价、折扣、税费。

不使用运算符的困惑:

  • 如何在程序中进行数学计算?
  • 如何判断价格是否达到折扣门槛?
  • 如何组合多个条件?

使用运算符的解决方案:

python
# 购物计算
price: float = 100.0
quantity: int = 3

# 算术运算符:计算总价
total: float = price * quantity

# 比较运算符:判断是否享受折扣
has_discount: bool = total >= 200

# 逻辑运算符:组合多个条件
is_member: bool = True
final_discount: float = 0.9 if (has_discount and is_member) else 1.0

final_price: float = total * final_discount
print(f"原价:{total}元,折后:{final_price}元")

这就是运算符的价值:让程序能够进行计算和判断


运算符解决了什么问题?

运算符的本质是:让数据之间产生关系,进行计算或比较

就像你用计算器按加减乘除,Python 用运算符处理数据。

运算符的类型:

  1. 算术运算符:进行数学计算(+、-、*、/)
  2. 比较运算符:比较大小关系(>、<、==)
  3. 逻辑运算符:组合条件(and、or、not)
  4. 赋值运算符:给变量赋值(=、+=、-=)

运算符的最简用法

最常用的运算符只有4个:加、减、乘、除。

python
# 算术运算
print(10 + 5)   # 加法:15
print(10 - 5)   # 减法:5
print(10 * 5)   # 乘法:50
print(10 / 5)   # 除法:2.0

# 比较运算
print(10 > 5)   # 大于:True
print(10 == 5)  # 等于:False

# 逻辑运算
print(True and False)   # 与:False
print(True or False)    # 或:True

这就是运算符的基本用法。接下来我们详细学习各类运算符。


什么是运算符

运算符(Operator) 是用于执行特定运算的符号。

┌─────────────────────────────────────────┐
│            运算示意图                   │
├─────────────────────────────────────────┤
│                                         │
│   操作数  运算符  操作数  =  结果        │
│     │       │       │        │          │
│     3       +       5        8          │
│                                         │
└─────────────────────────────────────────┘

L1 理解层:会用

算术运算符

运算符一览

┌──────────┬──────────────────────────────┐
│  运算符  │          说明                │
├──────────┼──────────────────────────────┤
│    +     │ 加法                         │
│    -     │ 减法                         │
│    *     │ 乘法                         │
│    /     │ 除法(结果总是浮点数)        │
│    //    │ 整除(向下取整)             │
│    %     │ 取模(取余数)               │
│    **    │ 幂运算(乘方)               │
└──────────┴──────────────────────────────┘

示例代码

python
# 加减乘除
print(3 + 5)    # 8
print(10 - 3)   # 7
print(4 * 5)    # 20
print(10 / 2)   # 5.0(注意是浮点数)

# 整除和取模
print(10 // 3)  # 3(商)
print(10 % 3)   # 1(余数)

# 幂运算
print(2 ** 3)   # 8(2 的 3 次方)
print(4 ** 0.5) # 2.0(平方根)

整除说明(核心)

整除 //: 向下取整(朝负无穷方向)。

整除规则:
┌─────────────────────────────────────────────────────────────┐
│  整除 // 向下取整                                              │
│                                                              │
│  10 // 3 = 3      (正数:正常除法取整)                      │
│  -10 // 3 = -4    (负数:向下取整,不是 -3!)               │
│                                                              │
│  ⚠️ 注意:负数整除不是简单去掉小数                             │
│                                                              │
│  图解:                                                       │
│  数轴:... -5  -4  -3  -2  -1  0  1  2  3 ...                │
│                  ↑                    ↑                      │
│              -3.33 取整              3.33 取整               │
│              结果为 -4               结果为 3                 │
│              (向下)               (向下)                  │
└─────────────────────────────────────────────────────────────┘

最简示例

python
print(10 // 3)    # 3
print(-10 // 3)   # -4(注意不是 -3)

关键代码解释

表达式计算过程结果
10 // 310 / 3 = 3.33 → 向下取整3
-10 // 3-10 / 3 = -3.33 → 向下取整-4

取模应用

取模 %: 获取除法的余数。

取模应用场景:
┌─────────────────────────────────────────────────────────────┐
│  取模 % 的常见用途                                            │
│                                                              │
│  num % 2      判断奇偶(0=偶,1=奇)                          │
│  num % 10     获取最后一位数字                                │
│  num % 60     分钟转秒(循环计数)                            │
│  num % n      循环索引(0到n-1)                              │
└─────────────────────────────────────────────────────────────┘

最简示例

python
num = 7
print(num % 2)  # 1(奇数)

关键代码解释

表达式含义结果
num % 2 == 0奇偶判断True 为偶数
num % 10最后一位1234 % 10 = 4

详细示例

python
# 判断奇偶数
num = 7
if num % 2 == 0:
    print("偶数")
else:
    print("奇数")

# 获取最后一位数字
num = 1234
print(num % 10)  # 4

运算符优先级

优先级规则

优先级: 决定运算的执行顺序。

优先级结构图:
┌─────────────────────────────────────────────────────────────┐
│  算术运算符优先级(从高到低)                                   │
│                                                              │
│  优先级  运算符    示例                                        │
│  ─────────────────────────────────────                       │
│  最高    ()        (2 + 3) * 4  → 括号先算                   │
│  第二    **        2 ** 3 = 8   → 幂运算                     │
│  第三    * / // %  2 * 3 = 6    → 乘除类                     │
│  最低    + -       2 + 3 = 5    → 加减                       │
│                                                              │
│  记忆口诀:先括号,再乘方,接着乘除,最后加减                  │
│                                                              │
│  ⚠️ 建议:复杂表达式用括号明确顺序                             │
└─────────────────────────────────────────────────────────────┘

最简示例

python
print(2 + 3 * 4)  # 14(先乘后加)

关键代码解释

表达式执行顺序结果
2 + 3 * 4先 3*4=12,再 2+1214
(2 + 3) * 4先 2+3=5,再 5*420
2 * 3 ** 2先 3**2=9,再 2*918

比较运算符

运算符一览

┌──────────┬──────────────────────────────┐
│  运算符  │          说明                │
├──────────┼──────────────────────────────┤
│    ==    │ 等于                         │
│    !=    │ 不等于                       │
│    >     │ 大于                         │
│    <     │ 小于                         │
│    >=    │ 大于等于                     │
│    <=    │ 小于等于                     │
└──────────┴──────────────────────────────┘

注意:比较运算的结果是布尔值(True 或 False)

示例

python
# 数字比较
print(5 == 5)    # True
print(5 != 3)    # True
print(5 > 3)     # True
print(5 < 3)     # False

# 字符串比较(字典序)
print("apple" < "banana")  # True

# 链式比较
x = 5
print(1 < x < 10)  # True

重要区别

python
# = 赋值运算符
x = 5  # 把 5 赋值给 x

# == 比较运算符
x == 5  # 检查 x 是否等于 5

逻辑运算符

运算符一览

┌──────────┬──────────────────────────────┐
│  运算符  │          说明                │
├──────────┼──────────────────────────────┤
│   and    │ 与:两边都为真才为真         │
│   or     │ 或:有一边为真就为真         │
│   not    │ 非:取反                     │
└──────────┴──────────────────────────────┘

真值表

and 运算:
    True and True   = True
    True and False  = False
    False and True  = False
    False and False = False

or 运算:
    True or True   = True
    True or False  = True
    False or True  = True
    False or False = False

not 运算:
    not True  = False
    not False = True

示例

python
# and:两个条件都要满足
age = 20
has_money = True
can_buy = age >= 18 and has_money
print(can_buy)  # True

# or:只要满足一个条件
day = "Saturday"
is_weekend = day == "Saturday" or day == "Sunday"
print(is_weekend)  # True

# not:取反
is_raining = False
can_go_out = not is_raining
print(can_go_out)  # True

短路求值

python
# and 短路:第一个为 False,不计算第二个
print(False and print("不打印"))  # False

# or 短路:第一个为 True,不计算第二个
print(True or print("不打印"))  # True

真值判断(核心)

什么是真值判断

Python 在布尔上下文中会自动将任意值转换为 True 或 False。

┌─────────────────────────────────────────────────────────────┐
│          布尔上下文(自动进行真值判断的地方)                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. if 条件                                                 │
│     if x:         ← x 自动转换为 True/False                 │
│                                                             │
│  2. while 条件                                              │
│     while x:      ← x 自动转换为 True/False                 │
│                                                             │
│  3. 逻辑运算                                                │
│     x and y       ← x 和 y 自动转换                         │
│     x or y        ← x 和 y 自动转换                         │
│     not x         ← x 自动转换后取反                        │
│                                                             │
│  4. 三元表达式                                              │
│     a if x else b ← x 自动转换                              │
│                                                             │
│  核心概念:                                                  │
│  • bool(x) 函数返回 x 的真值                                │
│  • Python 不要求 x 是布尔类型,任意值都可以判断              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

假值完整列表

Python 中以下值在布尔上下文中被视为 False

┌─────────────────────────────────────────────────────────────┐
│          假值(Falsy)完整列表                                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  类型              假值示例                  说明            │
│  ─────────────────────────────────────────────             │
│  常量              None                      空值            │
│  常量              False                     布尔假          │
│                                                             │
│  数值              0                         整数零          │
│  数值              0.0                       浮点零          │
│  数值              0j                        复数零          │
│                                                             │
│  字符串            ''                        空字符串        │
│  字符串            ""                        空字符串        │
│  字符串            b''                       空字节串        │
│                                                             │
│  容器              ()                        空元组          │
│  容器              []                        空列表          │
│  容器              {}                        空字典          │
│  容器              set()                     空集合          │
│  容器              range(0)                  空范围          │
│                                                             │
│  ⚠️ 重要:                                                   │
│  • 空容器 ≠ None(但都视为 False)                           │
│  • 0 ≠ False(但都视为 False)                              │
│  • '' ≠ 空(但都视为 False)                                │
│                                                             │
│  ✅ 其他所有值都视为 True                                    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

最简示例

python
# 查看各种值的真值
print(bool(None))       # False
print(bool(False))      # False
print(bool(0))          # False
print(bool(0.0))        # False
print(bool(''))         # False
print(bool([]))         # False
print(bool({}))         # False

# 非假值都是 True
print(bool(1))          # True
print(bool('hello'))    # True
print(bool([1, 2]))     # True
print(bool({'a': 1}))   # True

关键代码解释

表达式真值原因
bool(None)FalseNone 是空值
bool(0)False数值零是假值
bool('')False空字符串是假值
bool([])False空列表是假值
bool([1])True非空列表是真值
bool('a')True非空字符串是真值

真值判断的惯用写法

原则:用真值判断而非显式比较,代码更简洁。

python
# ❌ 不推荐的写法(冗长)
if items == []:
    ...
if items != []:
    ...
if name == '':
    ...
if name != '':
    ...
if value == None:
    ...
if value != None:
    ...

# ✅ 推荐的惯用写法(简洁)
if not items:           # 空列表
    ...
if items:               # 非空列表
    ...
if not name:            # 空字符串
    ...
if name:                # 非字符串
    ...
if value is None:       # None 检查(用 is,不用 ==)
    ...
if value is not None:   # 非 None
    ...

对比说明:

写法等价于推荐原因
if not items:if items == []:惯用法,简洁
if items:if items != []:惯用法,简洁
if not name:if name == '':惯用法,简洁
if value is None:if value == None:None 用 is 判断身份
if value == None:可能有意外行为

⚠️ None 的特殊处理:

python
# None 检查用 is,不用 == 或 not
value = None

# ✅ 正确:用 is 检查身份
if value is None:
    print("值是 None")

# ✅ 正确:用 is not 检查非 None
if value is not None:
    print("值不是 None")

# ❌ 不推荐:用 == 检查
if value == None:  # 虽然结果正确,但语义不对
    ...

# ⚠️ 注意:not value 无法区分 None 和其他假值
value = None
name = ''
items = []

# 这三种情况 not 都返回 True
print(not value)   # True(None)
print(not name)    # True(空字符串)
print(not items)   # True(空列表)

# 所以检查 None 要用 is None

真值判断的实际应用

示例:栈的空检查

python
class Stack:
    def __init__(self) -> None:
        self._items: list[int] = []
    
    def push(self, item: int) -> None:
        self._items.append(item)
    
    def pop(self) -> int:
        # ✅ 惯用写法:用 not 检查空列表
        if not self._items:
            raise IndexError("栈为空")
        return self._items.pop()
    
    def is_empty(self) -> bool:
        # ✅ 惯用写法:直接返回真值(取反)
        return not self._items

# 使用
stack = Stack()
stack.push(1)
stack.push(2)
print(stack.pop())       # 2
print(stack.is_empty())  # False
print(stack.pop())       # 1
print(stack.is_empty())  # True

示例:用户输入检查

python
def greet(name: str) -> str:
    # ✅ 惯用写法:检查空字符串
    if not name:
        return "请输入姓名"
    return f"你好,{name}"

print(greet(""))         # "请输入姓名"
print(greet("张三"))      # "你好,张三"

示例:可选参数检查

python
def process(data: list[int] | None) -> int:
    # ✅ 惯用写法:区分 None 和空列表
    if data is None:
        return 0  # 无数据
    
    if not data:  # 空列表
        return -1  # 数据为空
    
    return sum(data)

print(process(None))     # 0(无数据)
print(process([]))       # -1(数据为空)
print(process([1, 2]))   # 3(有数据)

常见误区

误区1:认为 not 只对布尔值有效

python
# ❌ 误解:not 只用于 True/False
is_valid = True
if not is_valid:  # 这个理解正确
    ...

# ✅ 正解:not 对任意值有效
items = []
if not items:     # items 是列表,但 not 可以判断真值
    ...

误区2:混淆假值类型

python
# ❌ 误解:空列表和 None 是同一回事
if value == []:  # 这只匹配空列表,不匹配 None
    ...

# ✅ 正解:它们都是假值,但类型不同
value = None
print(value == [])   # False(类型不同)
print(not value)     # True(都是假值)
print(bool(value))   # False
print(bool([]))      # False

误区3:用 not 检查 None

python
# ❌ 不推荐:无法区分 None 和其他假值
def process(value: str | None) -> str:
    if not value:  # None 和 '' 都会进入这里
        return "无值"
    return value

# ✅ 正确:明确区分
def process(value: str | None) -> str:
    if value is None:
        return "无数据"
    if not value:  # 空字符串
        return "空字符串"
    return value

从简单到复杂:运算符的渐进应用

层级1:基础计算

python
# 简单的四则运算
a: int = 10
b: int = 3

print(a + b)  # 加:13
print(a - b)  # 减:7
print(a * b)  # 乘:30
print(a / b)  # 除:3.333...

层级2:高级算术

python
# 整除、取模、幂运算
a: int = 10
b: int = 3

print(a // b)  # 整除:3
print(a % b)   # 取模:1
print(a ** b)  # 幂:1000

层级3:比较判断

python
# 判断奇偶
num: int = 7
is_odd: bool = num % 2 != 0
print(f"{num}是奇数:{is_odd}")

# 范围判断
score: int = 85
is_pass: bool = 60 <= score <= 100
print(f"成绩有效:{is_pass}")

层级4:逻辑组合

python
# 多条件判断
age: int = 25
has_license: bool = True
can_drive: bool = age >= 18 and has_license
print(f"可以驾驶:{can_drive}")

# 会员优惠
is_member: bool = True
total: float = 150.0
has_discount: bool = is_member or total >= 200
print(f"享受折扣:{has_discount}")

层级5:复合运算

python
# 购物车计算
prices: list[float] = [29.9, 15.5, 8.0]
quantities: list[int] = [2, 1, 3]

# 计算总价
total: float = sum(p * q for p, q in zip(prices, quantities))

# 满减优惠
discount: float = 20.0 if total >= 100 else 0.0
final: float = total - discount

print(f"商品总价:{total:.1f}元")
print(f"满减优惠:{discount:.1f}元")
print(f"实付金额:{final:.1f}元")

综合应用:购物车结算程序

这个示例综合运用各类运算符:

python
# 购物车结算程序(Python 3.11+)
from typing import Any

def calculate_total(cart: list[dict[str, Any]]) -> dict[str, float]:
    """
    计算购物车总价
    
    Args:
        cart: 购物车商品列表
    
    Returns:
        结算信息字典
    """
    # 计算商品总价
    subtotal: float = sum(item["price"] * item["quantity"] for item in cart)
    
    # 判断是否满减(算术 + 比较)
    discount: float = 0.0
    if subtotal >= 200:
        discount = 30.0
    elif subtotal >= 100:
        discount = 15.0
    
    # 会员折扣(逻辑运算符)
    is_member: bool = True
    member_discount: float = 0.95 if is_member else 1.0
    
    # 计算最终价格
    after_discount: float = (subtotal - discount) * member_discount
    
    return {
        "subtotal": subtotal,
        "discount": discount,
        "member_rate": member_discount,
        "final": after_discount
    }

# 使用示例
cart: list[dict[str, Any]] = [
    {"name": "Python书籍", "price": 59.9, "quantity": 2},
    {"name": "编程键盘", "price": 199.0, "quantity": 1},
    {"name": "鼠标垫", "price": 29.9, "quantity": 1}
]

result: dict[str, float] = calculate_total(cart)

print("=== 购物车结算 ===")
print(f"商品总价:{result['subtotal']:.2f}元")
print(f"满减优惠:{result['discount']:.2f}元")
print(f"会员折扣:{result['member_rate']:.0%}")
print(f"实付金额:{result['final']:.2f}元")

这个程序展示了:

  • 算术运算符:计算价格和折扣
  • 比较运算符:判断满减条件
  • 逻辑运算符:会员资格判断
  • 运算符优先级:括号改变计算顺序
  • 类型提示的现代语法

关键代码说明:

代码含义为什么这样写
sum(item["price"] * item["quantity"] for item in cart)用生成器表达式计算所有商品的价格×数量之和一行完成循环乘法累加,比写 for 循环更简洁
subtotal >= 200比较运算:判断总价是否达到满减门槛比较运算结果为布尔值,用于控制 if 分支
0.95 if is_member else 1.0三元运算符:会员打 95 折,非会员不打折比 if-else 四行写法更简洁,适合简单二选一
(subtotal - discount) * member_discount括号提升优先级:先减满减,再乘折扣不加括号会先乘再减,计算结果不同
result['subtotal']:.2ff-string 访问字典键并格式化为两位小数:2f 控制输出精度,避免浮点数显示过长

L2 实践层:用好

推荐做法

做法原因示例
复杂表达式加括号明确顺序可读性优先,不依赖记忆优先级(a + b) * c
用链式比较替代 and更自然、更 Pythonic0 < x < 100
not items 检查空容器惯用法,比 len(items) == 0 简洁if not items:
is None 判断空值None 是单例,is 检查身份if value is None:
利用短路求值做防御性编程避免在空对象上调用方法if data and data.get("key"):
and/or 的真假短路做默认值简洁的默认值写法(谨慎使用)name = user_input or "匿名"
比较数值用 ==,不用 isis 比较身份,不可靠if x == 100:
//% 做循环计数整除+取模是周期问题的标准解法i // n 第几组,i % n 组内位置

反模式:不要这样做

python
# ❌ 错误:复杂表达式不加括号,依赖记忆优先级
result = a + b * c ** d // e % f  # 谁知道先算什么?

# ✅ 正确:加括号明确意图
result = a + (b * (c ** d) // e) % f
# 或拆分为多步:
temp = b * (c ** d)
result = a + (temp // e) % f
python
# ❌ 错误:用 == 比较浮点数
x = 0.1 + 0.2
if x == 0.3:
    print("相等")  # 永远不会执行!

# ✅ 正确:用误差范围比较
import math
if math.isclose(x, 0.3):
    print("近似相等")
python
# ❌ 错误:用 len() 检查空容器
if len(items) == 0:
    ...

# ✅ 正确:用真值判断惯用法
if not items:
    ...
python
# ❌ 错误:用 is 比较数值
if x is 100:
    ...

# ✅ 正确:用 == 比较数值
if x == 100:
    ...
python
# ❌ 错误:混淆 = 和 ==
if x = 5:  # SyntaxError
    ...

# ✅ 正确:赋值用 =,比较用 ==
x = 5
if x == 5:
    ...
python
# ❌ 错误:and/or 短路误用(空字符串被当作假值)
name = user_input or "匿名"  # 如果用户输入空字符串,也会被替换
# 问题:空串 '' 和 None 都会被替换成 "匿名"

# ✅ 正确:明确只处理 None
name = user_input if user_input is not None else "匿名"
# 或用三元表达式
name = "匿名" if user_input is None else user_input

常见陷阱

陷阱说明解决方案
浮点数比较0.1 + 0.2 != 0.3math.isclose()
整除负数方向-10 // 3 = -4 不是 -3记住是向下取整
短路求值副作用cond and expensive_func() 中 expensive_func 可能不执行不应依赖短路求值触发副作用
and/or 返回值x and y 返回的是值(不是 True/False)需要布尔值时包装 bool(x and y)
not 优先级高于 and/ornot a and b = (not a) and b不明确时加括号
除数为 010 / 0 抛 ZeroDivisionError先检查 if b != 0

适用场景

场景是否推荐原因
数字计算✅ 使用算术运算符基础功能
条件判断✅ 使用比较运算符基础功能
多条件组合✅ 使用逻辑运算符简洁清晰
范围判断✅ 使用链式比较 0 < x < 100x > 0 and x < 100 更自然
空值检查✅ 用 is None / not items惯用法,简洁安全
浮点数科学计算❌ 用 decimal.Decimal避免精度误差
位运算❓ 使用 `&^ ~`
矩阵运算❌ 用 NumPy专业库提供更好的性能和功能
三态逻辑(含 None)❌ 用显式判断and/or 对 None 行为可能反直觉

L3 专家层:深入

Python 如何实现运算符

短路求值的内部机制
短路求值字节码分析:
┌─────────────────────────────────────────────────────────────┐
│          and / or 短路求值的实现                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  x and y 的执行语义:                                         │
│  ──────────────                                              │
│  if x is False:                                              │
│      return x          ← 短路:不计算 y                      │
│  else:                                                      │
│      return y          ← 返回 y 的值(非布尔化)              │
│                                                             │
│  x or y 的执行语义:                                          │
│  ─────────────                                            │
│  if x is True:                                               │
│      return x          ← 短路:不计算 y                      │
│  else:                                                      │
│      return y          ← 返回 y 的值(非布尔化)              │
│                                                             │
│  ⚠️ 关键:and/or 返回的是"值",不是 True/False!             │
│  0 and 5   → 0 (返回第一个假值)                            │
│  3 and 5   → 5 (返回最后一个真值)                           │
│  0 or 5    → 5 (返回第一个真值)                             │
│  3 or 5    → 3 (返回第一个真值)                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

验证代码:

python
# and/or 返回值的证明
print(0 and 5)    # 0(返回第一个假值)
print(3 and 5)    # 5(返回最后一个值)
print(0 or 5)     # 5(返回第一个真值)
print(3 or 5)     # 3(返回第一个真值)

# 短路求值验证
def side_effect():
    print("执行了!")
    return True

print(False and side_effect())  # 不输出 "执行了!"
print(True or side_effect())    # 不输出 "执行了!"

# 查看 and/or 的字节码
from dis import dis
dis("a and b")
# 关键指令:
# JUMP_IF_FALSE_OR_POP → 如果 a 为假则跳转(短路)
dis("a or b")
# 关键指令:
# JUMP_IF_TRUE_OR_POP → 如果 a 为真则跳转(短路)
整除(//)的内部实现
整除实现的数学原理:
┌─────────────────────────────────────────────────────────────┐
│          整除 // 的内部机制                                     │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  a // b 等价于 floor(a / b)                                  │
│                                                              │
│  floor(x) = 不大于 x 的最大整数                               │
│                                                              │
│  正向:                                                       │
│  10 / 3 = 3.333...  → floor(3.333) = 3  → 10 // 3 = 3       │
│                                                              │
│  负向:                                                       │
│  -10 / 3 = -3.333... → floor(-3.333) = -4 → -10 // 3 = -4   │
│                                                              │
│  除数和余数的关系(Python 保证):                              │
│  a = b * (a // b) + (a % b)                                  │
│                                                              │
│  验证:                                                       │
│  10 = 3 * (10 // 3) + (10 % 3) = 3 * 3 + 1 = 9 + 1 = 10 ✓  │
│  -10 = 3 * (-10 // 3) + (-10 % 3) = 3 * (-4) + 2 = -12+2 ✓│
│                                                              │
│  注意:不同语言对负数取模的结果不同:                           │
│  Python: -10 % 3 = 2(余数非负)                             │
│  C/Java: -10 % 3 = -1(余数与被除数同号)                    │
│                                                              │
└─────────────────────────────────────────────────────────────┘

验证代码:

python
# 整除和取模的一致性
a, b = -10, 3
print(a == b * (a // b) + (a % b))  # True(Python 的数学保证)

# 对比不同语言的余数
print(-10 % 3)   # 2(Python:余数非负)
# C/Java:结果是 -1

# 查看字节码
from dis import dis
dis("10 // 3")
# BINARY_FLOOR_DIVIDE
dis("10 % 3")
# BINARY_MODULO
运算符重载协议
运算符的魔术方法映射:
┌─────────────────────────────────────────────────────────────┐
│          运算符与魔术方法的对应关系                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  运算符    魔术方法          运算符    魔术方法               │
│  ──────    ────────          ──────    ────────              │
│  +        __add__            ==       __eq__                 │
│  -        __sub__            !=       __ne__                 │
│  *        __mul__            <        __lt__                 │
│  /        __truediv__        >        __gt__                 │
│  //       __floordiv__       <=       __le__                 │
│  %        __mod__            >=       __ge__                 │
│  **       __pow__            and      无法重载               │
│                                                             │
│  ⚠️ and/or/not 不能被重载!(它们是关键字,不是运算符方法)     │
│                                                             │
│  链式比较的实现:                                              │
│  a < b < c 编译为 a < b and b < c(但 b 只计算一次)           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

验证代码:

python
# 运算符重载示例
class Vector:
    def __init__(self, x: int, y: int) -> None:
        self.x = x
        self.y = y
    
    def __add__(self, other: "Vector") -> "Vector":
        return Vector(self.x + other.x, self.y + other.y)
    
    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Vector):
            return NotImplemented
        return self.x == other.x and self.y == other.y
    
    def __repr__(self) -> str:
        return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)  # Vector(4, 6)
print(v1 == v2) # False

# 查看链式比较的字节码
from dis import dis
dis("a < b < c")
# 可以看到 b 只被 LOAD 一次,但比较两次

性能考量

操作时间复杂度说明
+, -, *, / (整数)O(1) ~ O(n)小整数 O(1),大整数随位数增长
+, -, *, / (浮点)O(1)IEEE 754 硬件指令
** (幂运算)O(log n)快速幂算法
//, %O(1) ~ O(n)同除法复杂度
比较 ==, <, >O(1) ~ O(n)字符串比较 O(min(len(a), len(b)))
and/orO(1)最多计算两个操作数
notO(1)单操作数取反
链式比较 a < b < cO(1)两个比较,b 只计算一次
python
import timeit

# 幂运算 vs 乘法
print(timeit.timeit("2 ** 100", number=1_000_000))
# → ~0.03 秒

print(timeit.timeit("2 * 2 * 2 * 2 * 2", number=1_000_000))
# → ~0.02 秒(少量乘法更快,但幂运算在大指数时显著更快)

# 链式比较 vs 两次比较
print(timeit.timeit("0 < x < 100", setup="x = 50", number=10_000_000))
# → ~0.3 秒

print(timeit.timeit("0 < x and x < 100", setup="x = 50", number=10_000_000))
# → ~0.4 秒(链式比较略快,因为 x 只计算一次)

知识关联

运算符知识关联:

    ┌─────────────────────┐
    │      Python 运算符   │
    └─────────────────────┘

    ┌─────────┼─────────┬─────────┐
    ↓         ↓         ↓         ↓
┌────────┐ ┌────────┐ ┌────────┐ ┌────────────┐
│ 算术   │ │ 比较   │ │ 逻辑   │ │ 位运算     │
│+ - * / │ │== != <> │ │and or  │ │& | ^ ~    │
│// % ** │ │>= <=   │ │not     │ │<< >>      │
└────────┘ └────────┘ └────────┘ └────────────┘
    │         │         │
    ↓         ↓         ↓
┌──────────────────────────────────────────┐
│         魔术方法协议(__add__ 等)         │
│         运算符可被自定义类重载            │
└──────────────────────────────────────────┘


    ┌─────────────────────┐
    │   短路求值           │
    │   JUMP_IF_FALSE_OR  │
    │   JUMP_IF_TRUE_OR   │
    └─────────────────────┘


    ┌─────────────────────┐     ┌─────────────────────┐
    │   真值判断协议        │────→│  流程控制(if/while)│
    │   __bool__ > __len__│     │  基于真值执行分支    │
    └─────────────────────┘     └─────────────────────┘

设计动机

设计选择原因影响
and/or 返回值而非布尔值灵活用于默认值模式 name = input or "匿名"同时带来陷阱(空字符串也是假值)
Python 的 -10 % 3 = 2(非负)数学上更一致:a = b*q + r 且 `0 ≤ r <b
// 向下取整而非截断保证 a == b*(a//b) + a%b 恒成立负数场景需要适应
链式比较 a < b < c更接近数学写法b 只计算一次,性能略优

本章小结

┌─────────────────────────────────────────────────────────────┐
│                      运算符 知识要点                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   算术运算符:                                               │
│   ✓ + - * / // % **                                        │
│   ✓ / 结果总是浮点数                                        │
│                                                             │
│   比较运算符:                                               │
│   ✓ == != > < >= <=                                        │
│   ✓ 结果是布尔值                                            │
│                                                             │
│   逻辑运算符:                                               │
│   ✓ and or not                                             │
│   ✓ 支持短路求值                                            │
│                                                             │
│   真值判断(核心):                                          │
│   ✓ 假值:None, False, 0, '', [], {}, set()                 │
│   ✓ 惯用写法:if not items:(检查空)                       │
│   ✓ None 检查:if value is None:(用 is)                   │
│   ✓ 区分 None 和空容器                                      │
│                                                             │
│   优先级:                                                   │
│   ✓ () > ** > * / // % > + -                               │
│                                                             │
│   实际应用:                                                 │
│   ✓ 价格计算、条件判断、优惠规则                            │
│   ✓ 空值检查、栈空判断                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘