# 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
文章作者:小明

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

木 白 微信支付

微信支付

木 白 支付宝

支付宝

木 白 贝宝

贝宝