PEP 498 – Literal String Interpolation Python,字面字符串插值

也就是传说中的f-string语法,在字符串前添加 fF 前缀,然后在 {} 中放入 Python 表达式:

name = "Alice"
age = 30

# 基本用法
print(f"Hello, {name}! You are {age} years old.")
# 输出:Hello, Alice! You are 30 years old.

# 支持任意表达式
print(f"5 + 3 = {5 + 3}")  # 数学运算
# 输出:5 + 3 = 8

print(f"{'uppercase'.upper()}")  # 函数调用
# 输出:UPPERCASE

print(f"{age=}")  # Python 3.8+ 支持的自解释表达式
# 输出:age=30

{} 内使用 : 分隔表达式和格式说明符,支持数字格式化、日期格式化等:

# 数字格式化
pi = 3.1415926
print(f"Pi is approximately {pi:.2f}")  # 保留两位小数
# 输出:Pi is approximately 3.14

# 日期格式化
from datetime import datetime
now = datetime.now()
print(f"Today is {now:%Y-%m-%d}")  # 按指定格式输出日期
# 输出:Today is 2023-10-01

# 字符串对齐
text = "hello"
print(f"{text:>10}")  # 右对齐,总宽度 10
# 输出:     hello

需要注意的几件事,第一个是双引号,需要外部为"(双双引号),内部为'(单双引号)

# 正确
print(f"She said: 'Hello, {name}!'")

# 错误(引号冲突)
print(f'She said: "Hello, {name}!"')  # 会导致语法错误

如果需要在 f-string 中使用括号,使用额外的括号进行转义:

print(f"{{1, 2, 3}} is a set")  # 输出:{1, 2, 3} is a set

通常来说,f-string 的性能是要好于 python 之前的%表示和format表示的,因为 f-string 是在运行时动态计算填充。但是也有例外,代表性的例子就是logging,我们观察如下代码:

import logging
import time

logging.basicConfig(level=logging.INFO)  # 仅输出 INFO 及以上级别日志

for i in range(100000):
    # 即使日志级别为 INFO,DEBUG 级别的 f-strings 仍会被拼接(但不输出)
    logging.debug(f"循环第 {i} 次,当前时间: {time.time()}, 状态: {i % 2 == 0}")

很明显日志的等级为DEBUG,低于配置的INFO等级,不应该被打印出来。但是表达式的内容还是计算了。这种情况就需要用logging自带的format功能了,限于篇幅,不在这里给出。

PEP 572 – Assignment Expressions,表达式内赋值

介绍

海象运算符:=(为什么叫这个名字,因为长得像海象吗???),该特性仅在 Python 3.8+ 支持

我们常常需要声明一些临时变量,用完就扔的那种,放在循环或者判断条件里:

# 传统写法
data = input("Enter something: ")
if len(data) > 5:
    print(f"Received: {data}")

虽然data的作用范围是全局,但是显然这里单独一行代码确实很啰嗦。如果使用海象运算符,就可以这么写:

# 使用海象运算符
if (data := input("Enter something: ")) and len(data) > 5:
    print(f"Received: {data}")

这就相当于把上面的一行代码塞进来了。注意,这两种写法是完全等效的!也就是说data的作用范围依然是全局:

# 使用海象运算符
if (data := input("Enter something: ")) and len(data) > 5:
    print(f"Received: {data}")
print(data)

这样的代码是可以运行的!(可能比较反常识,尤其是对于我这种C++/Java出身的程序员来说,但是我觉得是为了兼容性)

用法

这就有很多花样了。除了上面提到的简化代码,海象运算符的另外一个作用在于减少重复计算:
以下面的代码为例:

# 传统写法
results = [complex_calculation(x) for x in data if complex_calculation(x) > 10]

这里实际上complex_calculation计算了两次(python居然不会自动优化这种结构)
使用海象运算符就会减少一次运算:

# 使用海象运算符
results = [y for x in data if (y := complex_calculation(x)) > 10]

争议

我翻了翻知乎,这玩意从诞生开始就一直存在争议。我认同其中的一种观点:

语言提供了更多特性和选择的机会,但控制权是开发者手里的,就像元类、描述符、dataclass 甚至装饰器等等都是有适用场景的。

鉴于我所在的项目没有用这个特性,我这里就不写更多内容了。

PEP 3105 – Make print a function,print 改为函数

我只想说,python 从 2 到 3 的破坏性改动也不止这一处了,多这一个又何妨。

由于我手里没有 python 2 的环境,这些都是我查的资料。
在 Python 2 中,print 是一个特殊的语法结构(语句),而非普通函数:

# Python 2 的写法
print "Hello, world!"  # 无需括号
print x, y             # 打印多个值,用逗号分隔
print >> sys.stderr, "Error"  # 重定向输出到 stderr

这样带来了很多问题(甚至C的printf都是函数)因此 python3 将其修改为函数。

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐