欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python 3.8.0 正式版发布,新特性初体验

程序员文章站 2023-11-18 19:55:10
北京时间 10 月 15 日,Python 官方发布了 3.8.0 正式版,该版本较 3.7 版本再次带来了多个非常实用的新特性。 ......

北京时间 10 月 15 日,python 官方发布了 3.8.0 正式版,该版本较 3.7 版本再次带来了多个非常实用的新特性。

赋值表达式

pep 572: assignment expressions

新增一种新语法形式::=,又称为“海象运算符”(为什么叫海象,看看这两个符号像不像颜表情),如果你用过 go 语言,应该对这个语法非常熟悉。

具体作用我们直接用实例来展示,比如在使用正则匹配时,以往版本中我们会如下写:

import re

pattern = re.compile('a')
data = 'abc'
match = pattern.search(data)
if match is not none:
    print(match.group(0))

而使用赋值表达式时,我们可以改写为:

if (match := pattern.search(data)) is not none:
    print(match.group(0))

在 if 语句中同时完成了求值、赋值变量、变量判断三步操作,再次简化了代码。

下面是在列表表达式中的用法:

filtered_data = [y for x in data if (y := func(x)) is not none]

强制位置参数

pep 570: python positional-only parameters

新增一个函数形参标记:/,用来表示标记左侧的参数,都只接受位置参数,不能使用关键字参数形式。

>>> def pow(x, y, z=none, /):
...     r = x ** y
...     return r if z is none else r%z
...
>>> pow(5, 3)
125
>>> pow(x=5, y=3)
traceback (most recent call last):
  file "<stdin>", line 1, in <module>
typeerror: pow() takes no keyword arguments

这实际上是用纯 python 代码来模拟现有 c 代码实现的内置函数中类似功能,比如内置函数 len('string') 传参是不能使用关键字参数的。

runtime 审计钩子

pep 578: python runtime audit hooks

这让我们可以对某些事件和 api 添加一些钩子,用于在运行时监听事件相关的参数。

比如这里监听 urllib 请求:

>>> import sys
>>> import urllib.request
>>> def audit_hook(event, args):
...     if event in ['urllib.request']:
...         print(f'{event=} {args=}')
...
>>> sys.addaudithook(audit_hook)
>>> urllib.request.urlopen('https://httpbin.org/get?a=1')
event = 'urllib.request' args =( 'https://httpbin.org/get?a=1' , none , {}, 'get' )
<http.client.httpresponse object at 0x108f09b38>

官方内置了一些 api,具体可查看 pep-578 规范文档,也可以自定义。

f-strings 支持等号

在 python 3.6 版本中增加了 f-strings,可以使用 f 前缀更方便地格式化字符串,同时还能进行计算,比如:

>>> x = 10
>>> print(f'{x+1}')
11

在 3.8 中只需要增加一个 = 符号,即可拼接运算表达式与结果:

>>> x = 10
>>> print(f'{x+1=}')
'x+1=11'

这个特性官方指明了适用于 debug。

asyncio 异步交互模式

在之前版本的 python 交互模式中(repl),涉及到 asyncio 异步函数,通常需要使用 asyncio.run(func()) 才能执行。

而在 3.8 版本中,当使用 python -m asyncio 进入交互模式,则不再需要 asyncio.run

>>> import asyncio
>>> async def test():
...     await asyncio.sleep(1)
...     return 'test'
...
>>> await test()
'test'

跨进程共享内存

在 python 多进程中,不同进程之间的通信是常见的问题,通常的方式是使用 multiprocessing.queue 或者 multiprocessing.pipe,在 3.8 版本中加入了 multiprocessing.shared_memory,利用专用于共享 python 基础对象的内存区域,为进程通信提供一个新的选择。

from multiprocessing import process
from multiprocessing import shared_memory

share_nums = shared_memory.shareablelist(range(5))

def work1(nums):
    for i in range(5):
        nums[i] += 10
    print('work1 nums = %s'% nums)

def work2(nums):
    print('work2 nums = %s'% nums)

if __name__ == '__main__':
    p1 = process(target=work1, args=(share_nums, ))
    p1.start()
    p1.join()
    p2 = process(target=work2, args=(share_nums, ))
    p2.start()

# 输出结果:
# work1 nums = [10, 11, 12, 13, 14]
# work2 nums = [10, 11, 12, 13, 14]

以上代码中 work1 与 work2 虽然运行在两个进程中,但都可以访问和修改同一个 shareablelist 对象。

@cached_property

熟悉 python web 开发的同学,对 werkzeug.utils.cached_propertydjango.utils.functional.cached_property 这两个装饰器一定非常熟悉,它们是内置 @property 装饰器的加强版,被装饰的实例方法不仅变成了属性调用,还会自动缓存方法的返回值。

现在官方终于加入了自己的实现:

>>> import time
>>> from functools import cached_property
>>> class example:
...     @cached_property
...     def result(self):
...         time.sleep(1) # 模拟计算耗时
...         print('work 1 sec...')
...         return 10
...
>>> e = example()
>>> e.result
work 1 sec...
10
>>> e.result # 第二次调用直接使用缓存,不会耗时
10

其他改进

  • pep 587: python 初始化配置
  • pep 590: vectorcall,用于 cpython 的快速调用协议
  • finally: 中现在允许使用 continue
  • typed_ast 被合并回 cpython
  • pickle 现在默认使用协议4,提高了性能
  • load_global 速度加快了 40%
  • unittest 加入了异步支持
  • 在 windows 上,默认 asyncio 事件循环现在是 proactoreventloop
  • 在 macos 上,multiprocessing 启动方法默认使用 spawn

更多具体变化,可查看 what’s new in python 3.8


本文属于原创内容,首发于微信公众号「面向人生编程」,如需转载请在公众号后台留言。

Python 3.8.0 正式版发布,新特性初体验

关注后回复以下信息获取更多资源
回复【资料】获取 python / java 等学习资源
回复【插件】获取爬虫常用的 chrome 插件
回复【知乎】获取最新知乎模拟登录