Python 官网静悄悄地发布了一则大消息:正式发布 Python 3.8.0!新版本较3.7版增加了一大波新功能和优化,来与 AI 大咖一起参与讨论吧~

今天,Python 官网宣布,正式发布 Python 3.8.0

python3 使用界面 python3.8界面介绍_python3 使用界面

Python 3.8.0 现已推出。

代表 Python 开发社区和 Python 3.8 发布团队,我们很高兴地宣布 Python 3.8.0 现在已经可以使用。

Python 3.8.0 是 Python 语言的最新正式版,包含许多新功能和优化。

Python 的大多数第三方库也应该很快就会支持 3.8.0 软件包。

有关 3.8 版本功能的更多信息,请参阅 “Python 3.8 新特性” 文档。所有更改的详细信息都可以在更改日志中找到。

从 2019 年 12 月开始,3.8 系列的维护版本将定期每两个月发布一次。

我们希望您喜欢 Python 3.8!

感谢所有帮助 Python 开发和这些发布的志愿者!欢迎通过志愿或组织捐赠支持 Python 软件基金会的工作。

Python 3.8.0 重要新特性&优化

那么,这次新发布的 Python 3.8.0 有哪些重要的改进呢?以下是是 Python 3.8 相比 3.7 的新增特性。

  • PEP 572,赋值表达式
  • PEP 570,仅限位置形参
  • PEP 587,Python 初始化配置(改进的嵌入)
  • PEP 590,Vectorcall:用于 CPython 的快速调用协议
  • PEP 578, Python Runtime Audit Hooks
  • PEP 574,具有外部数据缓冲区的 pickle 协议 5
  • 与打字相关:PEP 591(最终限定词),PEP 586(文学类型)和 PEP 589(TypedDict)
  • 用于已编译字节码文件的并行文件系统缓存
  • 调试构建使用与发布构建相同的 ABI
  • f - 字符串支持 = 用于自动记录表达式和调试文档
  • 在 Windows 上,默认 asyncio 事件循环现在是 ProactorEventLoop
  • 在 macOS 上,spawn 启动方法默认使用 multiprocessing
  • multiprocessing 现在可以使用共享内存段来避免进程之间的酸洗成本
  • typed_ast 被合并回 CPython
  • LOAD_GLOBAL 速度加快了 40%
  • pickle 现在默认使用协议 4,提高了性能

接下来,我们重点来看几个(来自Python 3.8 文档)。

赋值表达式

Python 3.8.0 有一个新的语法 :=,它将值赋给一个更大的表达式中的变量。它被亲切地称为 “海象运算符”(walrus operator),因为它长得像海象的眼睛和象牙。

python3 使用界面 python3.8界面介绍_python3 使用界面_02

海象

这个 “海象运算符” 在某些时候可以让你的代码更整洁,比如:

在这个示例中,赋值表达式可以避免调用 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]

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

了解详情:https://www.python.org/dev/peps/pep-0572

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

仅限位置形参

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

在下面的例子中,形参 a 和 b 为仅限位置形参,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:

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

了解详情:https://www.python.org/dev/peps/pep-0570

(由 Pablo Galindo 在 bpo-36540 中贡献。)

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

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

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

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

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

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

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 587: Python 初始化配置 

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

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

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

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

了解详情:https://www.python.org/dev/peps/pep-0590

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

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

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

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