# PEP 572: Assignment Expressions
海象表达式,用途是赋值给中间变量
# 示例一
pattern = re.compile('s') | |
data = 'ss' | |
# 注意此处,会执行两次 re.match (data) | |
if pattern.match(data): | |
print(pattern.match(data).group(0)) |
pattern = re.compile('s') | |
data = 'ss' | |
# 注意此处变化,使用海象表达式可以减少一次 re.match (data) 的执行 | |
if (match := pattern.match(data)) is not None: | |
print(match.group(0)) |
# 示例二
while 1: | |
line = fp.readline() | |
if not line: | |
break | |
print(line) |
while (line := fp.readline()): | |
print(line) |
# PEP 570: Python Positional-Only parameters
强制使用者用位置参数,原来在内置的 C 函数上有很多都用到了
In : __builtin__.eval | |
Out: <function eval(source, globals=None, locals=None, /)> | |
In : __builtin__.len | |
Out: <function len(obj, /)> | |
In : __builtin__.divmod | |
Out: <function divmod(x, y, /)> | |
# 看它们的签名,最后都有一个 /,/ 用途是 在 / 左面的这些参数,只能是位置参数 (不能是关键字参数): | |
In : divmod(3, 2) | |
Out: (1, 1) | |
In : divmod(x=3, y=2) | |
--------------------------------------------------------------------------- | |
TypeError Traceback (most recent call last) | |
<ipython-input-28-6668f56246b2> in <module> | |
----> 1 divmod(x=3, y=2) | |
TypeError: divmod() takes no keyword arguments |
如果使用关键字参数的方式,会报错。就是因为强制使用者用位置参数!
通过 PEP 570,我们写的 Python 代码也可以支持了。你可以这样写:
def name(p1, p2, /, p_or_kw, *, kw): | |
def name(p1, p2=None, /, p_or_kw=None, *, kw): | |
def name(p1, p2=None, /, *, kw): | |
def name(p1, p2=None, /): | |
def name(p1, p2, /, p_or_kw): | |
def name(p1, p2, /): |
# PEP 578: Python Runtime Audit Hooks
现在可以给 Python 运行时添加审计钩子:
In : import sys | |
...: import urllib.request | |
...: | |
...: | |
...: def audit_hook(event, args): | |
...: if event in ['urllib.Request']: | |
...: print(f'Network {event=} {args=}') | |
...: | |
...: sys.addaudithook(audit_hook) | |
In : urllib.request.urlopen('https://httpbin.org/get?a=1') | |
Network event='urllib.Request' args=('https://httpbin.org/get?a=1', None, {}, 'GET') | |
Out: <http.client.HTTPResponse at 0x10e394310> |
# Multiprocessing shared memory
可以跨进程直接访问同一内存 (共享):
# IPython 进程 A | |
In : from multiprocessing import shared_memory | |
In : a = shared_memory.ShareableList([1, 'a', 0.1]) | |
In : a | |
Out: ShareableList([1, 'a', 0.1], name='psm_d5d6ba1b') # 注意 name | |
# IPython 进程 B (另外一个终端进入 IPython) | |
In : from multiprocessing import shared_memory | |
In : b = shared_memory.ShareableList(name='psm_d5d6ba1b') # 使用 name 就可以共享内存 | |
In : b | |
Out: ShareableList([1, 'a', 0.1], name='psm_d5d6ba1b') |
# New importlib.metadata module
使用新的 importlib.metadata
模块可以直接读取第三方包的元数据:
In : from importlib.metadata import version, files, requires, distribution | |
In : version('flask') | |
Out: '1.1.1' | |
In : requires('requests') | |
Out: | |
['chardet (<3.1.0,>=3.0.2)', | |
'idna (<2.9,>=2.5)', | |
'urllib3 (!=1.25.0,!=1.25.1,<1.26,>=1.21.1)', | |
'certifi (>=2017.4.17)', | |
"pyOpenSSL (>=0.14) ; extra == 'security'", | |
"cryptography (>=1.3.4) ; extra == 'security'", | |
"idna (>=2.0.0) ; extra == 'security'", | |
"PySocks (!=1.5.7,>=1.5.6) ; extra == 'socks'", | |
'win-inet-pton ; (sys_platform == "win32" and python_version == "2.7") and extra == \'socks\''] | |
In : dist = distribution('celery') | |
In : dist.version | |
Out: '4.3.0' | |
In : dist.metadata['Requires-Python'] | |
Out: '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' | |
In : dist.metadata['License'] | |
In : dist.entry_points | |
Out: | |
[EntryPoint(name='celery', value='celery.__main__:main', group='console_scripts'), | |
EntryPoint(name='celery', value='celery.contrib.pytest', group='pytest11')] | |
In : files('celery')[8] | |
Out: PackagePath('celery/__init__.py') | |
In : dist.locate_file(files('celery')[8]) | |
Out: PosixPath('/Users/dongweiming/test/venv/lib/python3.8/site-packages/celery/__init__.py') |
# functools.cached_property
缓存属性 (cached_property) 是一个非常常用的功能,很多知名 Python 项目都自己实现过它,现在终于进入版本库了。
参考:functools.cached_property (Python 3.8) 作者:xiaoming
# functools.lru_cache 作为装饰器时可以不加参数
lru_cache 装饰器支持 max_size 和 typed2 个参数,如果对默认参数不敏感,过去只能这么用 (需要空括号):
In : @lru_cache() | |
...: def add(a, b): | |
...: return a + b | |
...: |
从 3.8 开始可以直接作为装饰器,而不是作为返回装饰器的函数 (不加括号):
In : @lru_cache | |
...: def add(a, b): | |
...: return a + b | |
...: |
# Asyncio REPL
参考:https://zhuanlan.zhihu.com/p/70030100
# F-strings DEBUG
参考:https://zhuanlan.zhihu.com/p/67826015
# Async Mock
单元测试模块 unittest 添加了 mock 异步代码的类:
In : import asyncio | |
In : from unittest.mock import AsyncMock, MagicMock | |
In : mock = AsyncMock(return_value={'json': 123}) | |
In : await mock() | |
Out: {'json': 123} | |
In : asyncio.run(mock()) | |
Out: {'json': 123} | |
In : async def main(*args, **kwargs): | |
...: return await mock(*args, **kwargs) | |
...: | |
In : asyncio.run(main()) | |
Out: {'json': 123} | |
In : mock = MagicMock() # AsyncMock 也可以 | |
In : mock.__aiter__.return_value = [1, 2, 3] | |
In : async def main(): | |
...: return [i async for i in mock] | |
...: | |
In : asyncio.run(main()) | |
Out: [1, 2, 3] |
# Generalized iterable unpacking in yield and return
参考:https://www.dongwm.com/post/iterable-unpacking/
# 本文引用:
参考文章:https://zhuanlan.zhihu.com/p/86670081
文章作者:小明