Skip to content

表达式与一行写法

条件表达式

Python 的一行条件表达式顺序是“真值在前,条件居中,假值在后”:

python
label = "adult" if age >= 18 else "minor"

它是表达式,可以嵌入函数参数或容器;但不要堆叠多层:

python
# 能运行,但阅读成本高
level = "high" if score >= 90 else "mid" if score >= 60 else "low"

分支只会执行一个,适合简单取值,不适合塞入具有副作用的复杂流程。

推导式

python
squares = [x * x for x in values if x >= 0]
mapping = {user.id: user.name for user in users}
unique = {normalize(x) for x in values}

阅读顺序对应普通循环:

python
result = []
for x in values:
    if x >= 0:
        result.append(x * x)

多个 for 从左到右嵌套:

python
pairs = [(x, y) for x in xs for y in ys if x != y]

不要用推导式只为副作用,例如 [print(x) for x in values] 会额外创建一组 None。此时使用普通 for

and 与 or 返回操作数

andor 返回最后求值的操作数,不保证返回 bool

python
name = supplied_name or "anonymous"
token = user and user.token

print(0 or 5)       # 5
print("ok" and 7)  # 7

这类默认值写法会把 0""[] 等合法假值也当作缺失。只有 None 表示缺失时,应显式判断:

python
timeout = default_timeout if supplied_timeout is None else supplied_timeout

比较链

python
0 <= index < len(items)

等价于 0 <= index and index < len(items),但中间表达式只求值一次。a < b > c 也合法,含义是 a < b and b > c,不是比较三个值递增。

海象运算符

:= 在表达式中赋值,适合避免重复计算:

python
if (count := len(items)) > 100:
    print(f"too many items: {count}")
python
while chunk := stream.read(8192):
    process(chunk)

括号常用于消除优先级歧义。不要用海象运算符把一行写成隐藏多次状态变化的脚本。

幂运算与负号

** 比左侧一元负号结合更紧,并且从右向左结合:

python
-2**2      # -(2**2) == -4
(-2)**2    # 4
2**3**2    # 2**(3**2) == 512

同时,2**-1 合法,因为右侧一元运算按语法规则参与指数表达式,结果为 0.5

取整除与余数

// 是向负无穷取整,不是简单截断小数:

python
-3 // 2  # -2
-3 % 2   # 1

Python 保持 a == (a // b) * b + (a % b)。处理跨语言算法时尤其要检查负数除法语义。

is 与 in

  • == 比较值,is 比较对象身份。
  • None 比较使用 is None
  • 不要因小整数或字符串驻留在某次运行中让 a is b 恰好为真,就用 is 比较数值或文本。
  • x in dict 检查 Key,不检查 Value。
  • x in generator 会消费元素,可能使后续迭代从中间继续或直接耗尽。

一行不等于更 Pythonic

一行表达式适合无副作用的映射、过滤和简单取值。出现以下情况应拆开:

  • 嵌套条件表达式。
  • 推导式包含多个副作用。
  • 需要记录中间变量解释业务含义。
  • 异常处理、资源释放或多个状态更新。
  • 为追求一行而重复昂贵计算。