如何在python lambda中使用wait

如何在python lambda中使用wait,python,python-3.x,asynchronous,lambda,async-await,Python,Python 3.x,Asynchronous,Lambda,Async Await,我正在尝试这样做: mylist.sort(key=lambda x: await somefunction(x)) 但我得到了这个错误: SyntaxError: 'await' outside async function 这是有意义的,因为lambda不是异步的 我试图使用async lambda x:…,但这会抛出SyntaxError:invalid syntax 国家: 可以提供异步lambda函数的语法,但此构造不在本PEP的范围内 但我无法确定该语法是否在CPython中实现

我正在尝试这样做:

mylist.sort(key=lambda x: await somefunction(x))
但我得到了这个错误:

SyntaxError: 'await' outside async function
这是有意义的,因为lambda不是异步的

我试图使用
async lambda x:…
,但这会抛出
SyntaxError:invalid syntax

国家:

可以提供异步lambda函数的语法,但此构造不在本PEP的范围内

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


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

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

mylist_annotated=[(等待mylist中x的某个_函数(x),x)]
mylist_注释的.sort()
mylist=[x代表键,x在mylist_注释中]
请注意,只有Python 3.6+才支持列表理解中的
await
表达式。如果您使用的是3.5,则可以执行以下操作:

mylist_annotated=[]
对于mylist中的x:
附加((等待一些函数(x,x))
mylist_注释的.sort()
mylist=[x代表键,x在mylist_注释中]

斯文·马纳奇的答案有一个边缘案例

如果您尝试对一个列表进行排序,该列表包含两个产生相同搜索键但不同且不可直接排序的项目,则该列表将崩溃

mylist = [{'score':50,'name':'bob'},{'score':50,'name':'linda'}]

mylist_annotated = [(x['score'], x) for x in mylist]
mylist_annotated.sort()
print( [x for key, x in mylist_annotated] )
将提供:

TypeError: '<' not supported between instances of 'dict' and 'dict'
我想如果您的数据中没有自然唯一的值,您可以在尝试排序之前插入一个值?也许是uuid

编辑:根据评论中的建议(谢谢!),您还可以使用operator.itemgetter:

import operator

mylist = [{'score':50,'name':'bob'},{'score':50,'name':'linda'}]

mylist_annotated = [(x['score'], x) for x in mylist]
mylist_annotated.sort(key=operator.itemgetter(0))
print( [x for key, x in mylist_annotated] )
通过将
lambda
async
生成器组合,可以模拟“
async
lambda
”:

key=lambda x:(为uu'in'等待某个函数(x)。uuu anext_uu()
可以将
()。\uuuu anext\uuuu()
移动到辅助对象,这可能会使模式更清晰:

def head(异步迭代器):返回异步迭代器。\uuuuanext\uuuu()
key=lambda x:head(等待函数(x)中的uu')
请注意,标准库中的排序方法/函数不是异步的。需要异步版本,例如(免责声明:我维护此库):

将asyncstdlib作为
mylist=wait a.sorted(mylist,key=lambda x:head(wait somefunction(x)表示uin'.'))

理解
lambda…:(…)。\uuuuuuanext\uuuu()
模式 一个“
async
lambda
”将是一个匿名异步函数,或者换句话说,是一个匿名函数,其计算结果是一个可等待函数。这与
async def
如何定义一个命名函数来计算一个可等待函数是并行的。
任务可以分为两部分:匿名函数表达式和嵌套等待表达式

  • 匿名函数表达式正是
    lambda…:…
    的意思

  • 等待的表情;然而:

    • (异步)生成器表达式隐式创建(协同路由)函数。由于异步生成器只需要异步运行,因此可以在sync函数()中定义它
    • 异步iterable可以通过its用作等待
这三个部分直接用于“
async
lambda
”模式:

#|可调用和作用域的正则lambda
#| |异步作用域的异步生成器表达式
#第一项是值得期待的
key=lambda x:(为uu'中的uu'等待某个函数(x)。uuu anext_uu()

异步生成器中in'.的
只需进行一次迭代。任何至少有一次迭代的变体都可以。

如果您已经定义了一个单独的异步函数,您可以进一步简化MisterMiyagi的答案:

mylist = await a.sorted(
    mylist, 
    key=somefunction)
如果要在等待密钥后更改密钥,可以使用:

下面是一个完整的示例程序:

import asyncio
import asyncstdlib as a

async def some_function(x):
    return x

async def testme():
    mylist=[2, 1, 3]

    mylist = await a.sorted(
        mylist, 
        key=lambda x: a.apply(lambda after: 1 / after, some_function(x)))
        
    print(f'mylist is: {mylist}')
    

if __name__ == "__main__":
    asyncio.run(testme())

我得到了一个
语法错误:理解中的'await'表达式不受支持
,因此我必须这样做(供将来参考):mylist_annotated=[]用于mylist中的x:mylist_annotated.append((wait some_function(x),x))mylist_annotated.sort()mylist=[x用于键,x用于mylist_annotated]现在它工作了,谢谢@没错,这是Python3.5中的一个限制,它在即将发布的Python3.6中被取消。发现了一个非常边缘的情况-请参阅我的答案:-)我认为这个边缘情况的最佳解决方案是将
操作符.itemgetter(0)
作为
排序()的关键函数传递给
sort()
。元组按字典顺序排序,因此相等的键将导致第二项的比较。通过显式地只选择第一项作为排序键,我们可以防止第二次比较。
mylist = await a.sorted(
    mylist, 
    key=lambda x: a.apply(lambda after: 1 / after, some_function(x)))
import asyncio
import asyncstdlib as a

async def some_function(x):
    return x

async def testme():
    mylist=[2, 1, 3]

    mylist = await a.sorted(
        mylist, 
        key=lambda x: a.apply(lambda after: 1 / after, some_function(x)))
        
    print(f'mylist is: {mylist}')
    

if __name__ == "__main__":
    asyncio.run(testme())