如何在python lambda中使用await

iCa*_*art 16 python lambda asynchronous python-3.x async-await

我正在尝试做这样的事情:

mylist.sort(key=lambda x: await somefunction(x))
Run Code Online (Sandbox Code Playgroud)

但我得到这个错误:

SyntaxError: 'await' outside async function
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为lambda不是异步的.

我尝试使用,async lambda x: ...但抛出一个SyntaxError: invalid syntax.

Pep 492声明:

可以提供异步lambda函数的语法,但是此构造超出了此PEP的范围.

但我无法确定是否在CPython中实现了该语法.

有没有办法声明异步lambda,或使用异步函数排序列表?

Sve*_*ach 19

你不能.没有async lambda,即使有,也没有把它作为关键函数传递给它list.sort(),因为一个关键函数将被称为同步函数而不是等待.一个简单的解决方法是自己注释您的列表:

mylist_annotated = [(await some_function(x), x) for x in mylist]
mylist_annotated.sort()
mylist = [x for key, x in mylist_annotated]
Run Code Online (Sandbox Code Playgroud)

  • @iCart对,这是Python 3.5中的一个限制,它在即将发布的Python 3.6中被提升. (5认同)

小智 10

await不能包含在lambda函数中。

这里的解决方案可以简化为:

from asyncio import coroutine, run


my_list = [. . .]


async def some_function(x) -> coroutine:
    . . .

my_list.sort(key=lambda x: await some_function(x))  # raises a SyntaxError
my_list.sort(key=lambda x: run(some_function(x))  # works
Run Code Online (Sandbox Code Playgroud)


Mis*_*agi 7

async lambda可以通过将 alambdaasync生成器组合来模拟“ ” :

key=lambda x: (await somefunction(x) for _ in '_').__anext__()
Run Code Online (Sandbox Code Playgroud)

可以将 移动( ).__anext__()到助手,这也可能使模式更清晰:

def head(async_iterator): return async_iterator.__anext__()

key=lambda x: head(await somefunction(x) for _ in '_')
Run Code Online (Sandbox Code Playgroud)

请注意,标准库中的排序方法/函数不是异步的。需要一个异步版本,例如asyncstdlib.sorted(免责声明:我维护这个库):

import asyncstdlib as a

mylist = await a.sorted(mylist, key=lambda x: head(await somefunction(x) for _ in '_'))
Run Code Online (Sandbox Code Playgroud)

理解lambda ...: (...).__anext__()模式

一个“ async lambda”将是一个匿名异步函数,或者换句话说,一个评估为等待的匿名函数。这与如何async def定义评估为等待的命名函数并行。
任务可以分为两部分:匿名函数表达式和嵌套的可等待表达式

  • 匿名函数表达式正是 a 的含义lambda ...: ...

  • awaitable 表达式只允许在协程函数中;然而:

    • 一个(异步)生成器表达式隐式地创建了一个(协程)函数。由于异步生成器只需要异步运行,它可以在同步函数中定义自 Python 3.7 起)。
    • 异步可迭代对象可以通过其__anext__方法用作等待对象。

这三个部分直接用于“ async lambda”模式:

#   | regular lambda for the callable and scope
#   |         | async generator expression for an async scope
#   v         v                                    v first item as an awaitable
key=lambda x: (await somefunction(x) for _ in '_').__anext__()
Run Code Online (Sandbox Code Playgroud)

for _ in '_'在异步发电机只能有一个确切的迭代。任何至少有一次迭代的变体都可以。