Python 3.8 有什么新变化

  • 编者 Raymond Hettinger

本文解释了 Python 3.8 相比 3.7 的新增特性。 完整的详情可参阅 更新日志

Python 3.8已于2019年10月14日发布。

新的特性

赋值表达式

新增的语法 := 可在表达式内部为变量赋值。 它被昵称为“海象运算符”因为它很像是 海象的眼睛和长牙

在这个示例中,赋值表达式可以避免调用 len() 两次:

if (n := len(a)) > 10:
    print(f"List is too long ({n} elements, expected <= 10)")

类似的益处还可出现在正则表达式匹配中需要使用两次匹配对象的情况中,一次检测用于匹配是否发生,另一次用于提取子分组:

discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
    discount = float(mo.group(1)) / 100.0

此运算符也适用于配合 while 循环计算一个值来检测循环是否终止,而同一个值又在循环体中再次被使用的情况:

# Loop over fixed length blocks
while (block := f.read(256)) != '':
    process(block)

另一个值得介绍的用例出现于列表推导式中,在筛选条件中计算一个值,而同一个值又在表达式中需要被使用:

[clean_name.title() for name in names
 if (clean_name := normalize('NFC', name)) in allowed_names]

请尽量将海象运算符的使用限制在清晰的场合中,以降低复杂性并提升可读性。

请参阅 PEP 572 了解详情。

(由 Morehouse 在 bpo-35224 中贡献。)

仅限位置形参

新增了一个函数形参语法 / 用来指明某些函数形参必须使用仅限位置而非关键字参数的形式。 这种标记语法与通过 help() 所显示的使用 Larry Hastings 的 Argument Clinic 工具标记的 C 函数相同。

在下面的例子中,形参 ab 为仅限位置形参,cd 可以是位置形参或关键字形参,而 ef 要求为关键字形参:

def f(a, b, /, c, d, *, e, f):
    print(a, b, c, d, e, f)

以下均为合法的调用:

f(10, 20, 30, d=40, e=50, f=60)

但是,以下均为不合法的调用:

f(10, b=20, c=30, d=40, e=50, f=60)   # b cannot be a keyword argument
f(10, 20, 30, 40, 50, f=60)           # e must be a keyword argument

这种标记形式的一个用例是它允许纯 Python 函数完整模拟现有的用 C 代码编写的函数的行为。 例如,内置的 pow() 函数不接受关键字参数:

def pow(x, y, z=None, /):
    "Emulate the built in pow() function"
    r = x ** y
    return r if z is None else r%z

另一个用例是在不需要形参名称时排除关键字参数。 例如,内置的 len() 函数的签名为 len(obj, /)。 这可以排除如下这种笨拙的调用形式:

len(obj='hello')  # The "obj" keyword argument impairs readability

另一个益处是将形参标记为仅限位置形参将允许在未来修改形参名而不会破坏客户的代码。 例如,在 statistics 模块中,形参名 dist 在未来可能被修改。 这使得以下函数描述成为可能:

def quantiles(dist, /, *, n=4, method='exclusive')
    ...

由于在 / 左侧的形参不会被公开为可用关键字,其他形参名仍可在 **kwargs 中使用:

>>>

>>> def f(a, b, /, **kwargs):
...     print(a, b, kwargs)
...
>>> f(10, 20, a=1, b=2, c=3)         # a and b are used in two ways
10 20 {'a': 1, 'b': 2, 'c': 3}

这极大地简化了需要接受任意关键字参数的函数和方法的实现。 例如,以下是一段摘自 collections 模块的代码:

class Counter(dict):

    def __init__(self, iterable=None, /, **kwds):
        # Note "iterable" is a possible keyword argument

用于已编译字节码文件的并行文件系统缓存

新增的 PYTHONPYCACHEPREFIX 设置 (也可使用 -X pycache_prefix) 可将隐式的字节码缓存配置为使用单独的并行文件系统树,而不是默认的每个源代码目录下的 __pycache__ 子目录。

缓存的位置会在 sys.pycache_prefix 中报告 (None 表示默认位置即 __pycache__ 子目录)。

(由 Carl Meyer 在 bpo-33499 中贡献。)

调试构建使用与发布构建相同的 ABI

Python 现在不论是以发布模式还是调试模式进行构建都将使用相同的 ABI。 在 Unix 上,当 Python 以调试模式构建时,现在将可以加载以发布模式构建的 C 扩展和使用稳定版 ABI 构建的 C 扩展。

发布构建和调试构建现在都是 ABI 兼容的:定义 Py_DEBUG 宏不会再启用 Py_TRACE_REFS 宏,它引入了唯一的 ABI 不兼容性。 Py_TRACE_REFS 宏添加了 sys.getobjects() 函数和 PYTHONDUMPREFS 环境变量,它可以使用新的 ./configure --with-trace-refs 构建选项来设置。 (由 Victor Stinner 在 bpo-36465 中贡献。)

在 Unix 上,C 扩展不会再被链接到 libpython,但 Android 和 Cygwin 例外。 现在静态链接的 Python 将可以加载使用共享库 Python 构建的 C 扩展。 (由 Victor Stinner 在 bpo-21536 中贡献。)

在 Unix 上,当 Python 以调试模式构建时,导入操作现在也会查找在发布模式下编译的 C 扩展以及使用稳定版 ABI 编译的 C 扩展。 (由 Victor Stinner 在 bpo-36722 中贡献。)

要将 Python 嵌入到一个应用中,必须将新增的 --embed 选项传给 python3-config --libs --embed 以获得 -lpython3.8 (将应用链接到 libpython)。 要同时支持 3.8 和旧版本,请先尝试 python3-config --libs --embed 并在此命令失败时回退到 python3-config --libs (即不带 --embed)。

增加一个 pkg-config python-3.8-embed 模块用来将 Python 嵌入到一个应用中: pkg-config python-3.8-embed --libs 包含 -lpython3.8。 要同时支持 3.8 和旧版本,请先尝试 pkg-config python-X.Y-embed --libs 并在此命令失败时回退到 pkg-config python-X.Y --libs (即不带 --embed) (请将 X.Y 替换为 Python 版本号)。

另一方面,pkg-config python3.8 --libs 不再包含 -lpython3.8。 C 扩展不可被链接到 libpython (但 Android 和 Cygwin 例外,这两者的情况由脚本处理);此改变是故意被设为向下不兼容的。 (由 Victor Stinner 在 bpo-36721 中贡献。)

f-字符串支持 = 用于自动记录表达式和调试文档

增加 = 说明符用于 f-string。 形式为 f'{expr=}' 的 f-字符串将扩展表示为表达式文本,加一个等于号,再加表达式的求值结果。 例如:

>>> user = 'eric_idle'
>>> member_since = date(1975, 7, 31)
>>> f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"

通常的 f-字符串格式说明符 允许更细致地控制所要显示的表达式结果:

>>>

>>> delta = date.today() - member_since
>>> f'{user=!s}  {delta.days=:,d}'
'user=eric_idle  delta.days=16,075'

= 说明符将输出整个表达式,以便详细演示计算过程:

>>>

>>> print(f'{theta=}  {cos(radians(theta))=:.3f}')
theta=30  cos(radians(theta))=0.866

(由 Eric V. Smith 和 Larry Hastings 在 bpo-36817 中贡献。)

PEP 578: Python 运行时审核钩子

此 PEP 添加了审核钩子和已验证开放钩子。 两者在 Python 与本机代码中均可用。允许以纯 Python 代码编写的应用和框架利用额外的通知,同时允许嵌入开发人员或系统管理员部署始终启用审核的 Python 版本。

请参阅 PEP 578 了解详情。

PEP 587: Python 初始化配置

PEP 587 增加了一个新的 C API 用来配置 Python 初始化,提供对整个配置过程的更细致控制以及更好的错误报告。

新的结构:

新的函数:

此 PEP 还为这些内部结构添加了 _PyRuntimeState.preconfig (PyPreConfig 类型) 和 PyInterpreterState.config (PyConfig 类型) 字段。 PyInterpreterState.config 成为新的引用配置,替代全局配置变量和其他私有变量。

请参阅 Python 初始化配置 获取详细文档。

请参阅 PEP 587 了解详情。

(由 Victor Stinner 在 bpo-36763 中贡献。)

Vectorcall: 用于 CPython 的快速调用协议

添加 "vectorcall" 协议到 Python/C API。 它的目标是对已被应用于许多类的现有优化进行正式化。 任何实现可调用对象的扩展类型均可使用此协议。

此特性目前为暂定状态,计划在 Python 3.9 将其完全公开。

请参阅 PEP 590 了解详情。

(由 Jeroen Demeyer 和 Mark Shannon 在 bpo-36974 中贡献。)

具有外部数据缓冲区的 pickle 协议 5

当使用 pickle 在 Python 进程间传输大量数据以充分发挥多核或多机处理的优势时,非常重要一点是通过减少内存拷贝来优化传输效率,并可能应用一些定制技巧例如针对特定数据的压缩。

pickle 协议 5 引入了对于外部缓冲区的支持,这样 PEP 3118 兼容的数据可以与主 pickle 流分开进行传输,这是由通信层来确定的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,451评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,172评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,782评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,709评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,733评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,578评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,320评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,241评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,686评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,878评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,992评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,715评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,336评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,912评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,040评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,173评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,947评论 2 355

推荐阅读更多精彩内容

  • Introduction This document gives coding conventions for t...
    wuutiing阅读 4,553评论 0 9
  • 最近一直单曲循环陈奕迅的 爱情呼叫转移,粤语版 富士山下,人这一辈子最怕听懂一首歌,那种揉碎了歌词,然后在你的生活...
    石头_aa94阅读 381评论 0 2
  • 昨天下午,我要去送今天孩子过周岁的饽饽。 我就屁颠屁颠的给大姐,打电话,接过电话,大姐一脸懵圈,我告诉她...
    佳佳喜饼阅读 754评论 0 0
  • 昨天晨起流清鼻涕,一个鼻眼儿不通气,受凉要感冒,左侧手液门透中渚,留针半个钟头,隔几分钟平补平泻捻针一次,之后鼻子...
    6896eb4c61c2阅读 888评论 0 0
  • 掐指数算 时日也许短暂 却恰好是遇见在最美的时光里 是人间的四月天 春华秋实 风花雪月 十指相扣 心心相惜...
    雅木风阅读 318评论 0 4