在Python中,您可以编写一个可迭代的生成器,如:
def generate(count):
for x in range(count):
yield x
# as an iterator you can apply the function next() to get the values.
it = generate(10)
r0 = next(it)
r1 = next(it) ...
尝试使用异步迭代器时,会出现'yield inside async'错误。 建议的解决方案是实现自己的生成器:
class async_generator:
def __aiter__(self):
return self
async def __anext__(self):
await asyncio.sleep()
return random.randint(0, 10)
# But when you try to get the next element
it = async_generator(10)
r0 = next(it)
您收到错误“'async_generator'对象不是迭代器”
我认为如果你打算将Iterator调用它,因为它具有完全相同的接口,所以我可以编写异步迭代器并在依赖于next()调用的框架上使用。 如果您需要重写整个代码以便能够使用异步,那么任何新的Python功能都是毫无意义的。
我错过了什么吗?
谢谢!
答案 0 :(得分:9)
所以,正如@bosnjak所说,你可以使用async:
globalSearch
但是如果你想手动迭代,你可以简单地写:
async for ITEM in A_ITER:
BLOCK1
else: # optional
BLOCK2
但我不建议这样做。
我认为如果你打算把它称为迭代器,因为它具有完全相同的接口,所以我可以编写异步迭代器并在依赖于next()调用的框架上使用
不,实际上它不一样。常规同步迭代器和异步迭代器之间存在差异。原因很简单:
这就是为什么不能将it = async_iterator()
await it.__anext__()
和iter
与异步迭代器一起使用的原因。并且您不能将它们用于需要同步迭代器的框架。因此,如果要使代码异步,则必须使用异步框架。 Here很少。
另外,我想谈谈迭代器和生成器。 Iterator是一个具有next
和__iter__
方法的特殊对象。而generator是一个包含__next__
表达式的特殊函数。 每个生成器都是迭代器,但反之亦然。异步迭代器和生成器也可以接受同样的事情。是的,因为python 3.6你可以编写异步生成器!
yield
您可以阅读PEP 525了解更多详情
答案 1 :(得分:4)
我相信为异步生成器引入了一个新的声明:
async for TARGET in ITER:
BLOCK
else:
BLOCK2
根据PEP 492。
基本上,这意味着你应该这样做:
async for number in generate(10):
print(number)
另外,请检查Differences from generators:
原生协程对象不实现 iter 和 next 方法。因此,它们不能迭代或传递给iter(), list(),tuple()和其他内置函数。它们也不能用于 for..in循环。尝试在本机上使用 iter 或 next coroutine对象将导致TypeError。
答案 2 :(得分:1)
我用它来通过列表进行异步循环
class AsyncRange(object):
def __init__(self, length):
self.length = length
self.i = 0
async def __aiter__(self):
return self
async def __anext__(self):
index = self.i
self.i += 1
if self.i <= self.length:
return index
else:
raise StopAsyncIteration
然后简单地说:
async for i in AsyncRange(my_list):
# your code