我的图片 · 在线免费的图片处理工具

前言

介绍一下Python中的:= 海象运算符(walrus operator),正式名称是“赋值表达式”。它可以在表达式内部完成赋值,并返回被赋的值。

它的核心价值是:当一个值在“条件判断”里算出来,后面还要用到时,不必算两遍,也不必把代码拆成两行。

正文

基本语法

x := 10          # 错误!赋值表达式本身必须加括号(单独使用时)
(x := 10)        # 正确,x 被赋值为 10

规则::= 所在的赋值表达式,如果出现在语句上下文(如 if、while、for 的目标以外的位置),通常需要加括号。

用途

while中使用

基本模式

while (line := input("> ")) != "quit":
    print("你输入了:", line)

执行顺序

  1. 执行 input("> "),得到字符串;
  2. 把结果赋给 line;
  3. 判断 line != "quit";
  4. 若成立,进入循环体,此时 line 可直接使用。

避免了这种重复:

line = input("> ")
while line != "quit":
    print("你输入了:", line)
    line = input("> ")   # 重复调用

配合迭代器

it = iter([1, 2, 3])
while (x := next(it, None)) is not None:
    print(x)

一次完成:取值 + 赋值 + 判断

前提是元素中不含 None,否则用哨兵对象:

_sentinel = object()
while (x := next(it, _sentinel)) is not _sentinel:
    print(x)

读取文件直到空行

with open("data.txt") as f:
    while (line := f.readline()):
        print(line, end="")

这里利用了 "空字符串为假" 的特性。

避免重复计算

while (n := expensive_computation()) > 0:
    process(n)

如果没有 :=,要么重复调用,要么拆成多行。

if中使用

if中使用也是比较常见。

正则匹配

import re

if (m := re.search(r"\d+", text)):
    print(m.group())

不用先写一行 m = re.search(...),再判断 if m:。

避免重复计算

if (length := len(data)) > 10:
    print("数据太长:", length)

len(data) 只算一次,length 后面还能用。

多重判断中复用结果

if (x := compute()) > 0 and x < 100:
    print("合法值:", x)
for中使用
for item in (items := ["a", "b", "c"]):
    print(item)
print("原列表:", items)

这里 items 是在 in 后面的表达式中赋值的。

# 避免重复计算 len()
result = [s for s in data if (n := len(s)) > 5]
# 条件里复用正则匹配结果
matches = [m.group(1) for line in lines if (m := pattern.match(line))]

注意顺序::= 赋的值,只能在当前 for / if 子句及其右侧使用。

for x in range(10):
    if (y := x * x) > 50:
        print(x, y)

作用域规则

赋值变量

:= 赋值的变量,作用于当前函数或模块作用域,不是语句块作用域。

if (x := 10) > 5:
    print(x)

print(x)   # 10,仍然可访问
# y 是当前函数或模块作用域的变量,出了 if 块照样能访问。

这和 for x in ... 的行为一致。

推导式中

在推导式中,:= 赋的值只在当前推导式内有效:

result = [y for x in range(3) if (y := x * 2)]
print(y)   #  NameError 
#推导式结束后,y是访问不到,类似函数中局部变量,出了函数就被释放了

Python 为了防止推导式“泄漏变量”而做的特殊处理。

result = [y for x in range(3) if (y := x * 2)]

等价于下面代码,返回y不为0的所有结果

result = []
for x in range(3):
    y = x * 2
    if y:            # 0 被过滤掉
        result.append(y)

小结

场景原因
while 循环需要“先算后判”避免重复调用
if 判断后要用结果避免重复计算
正则匹配非常自然
推导式中避免重复计算性能 + 简洁

:= 的意义:让“计算 → 判断 → 复用结果”这件事,可以在一个表达式里完成。

参考文章

  1. AI
  2. Python文档

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

none
暂无评论...