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) ...
非同期イテレータを使用しようとすると、「非同期内部での利回り」エラーが発生します。推奨される解決策は、独自のジェネレータを実装することです。
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機能は無意味です。
何か不足していますか?
ありがとう!
したがって、@ bosnjakが言ったように、asyncを次の目的で使用できます。
async for ITEM in A_ITER:
BLOCK1
else: # optional
BLOCK2
しかし、手動で反復したい場合は、次のように書くだけです。
it = async_iterator()
await it.__anext__()
しかし、私はそうすることをお勧めしません。
何か同じイテレータを持っているので、イテレータを呼び出す場合、非同期イテレータを記述して、next()呼び出しに大きく依存するフレームワークで使用できると思います
いいえ、実際には同じではありません。通常の同期イテレータと非同期イテレータには違いがあります。そしてそれにはいくつかの理由があります:
そのため、非同期イテレータでiter
およびnext
を使用することは不可能です。また、同期イテレータを想定しているフレームワークでは使用できません。したがって、コードを非同期にする場合は、非同期フレームワークも使用する必要があります。 ここ はその一部です。
また、イテレータとジェネレータについて簡単に説明します。イテレータは__iter__
および__next__
メソッドを持つ特別なオブジェクトです。一方、ジェネレータはyield
式を含む特別な関数です。 すべてのジェネレータはイテレータですが、その逆はありません。非同期のイテレータとジェネレータでも同じことが受け入れられます。はい、python 3.6なので、非同期ジェネレータを作成できます!
async def ticker(delay, to):
for i in range(to):
yield i
await asyncio.sleep(delay)
詳細は PEP 525 を参照してください。
新しいステートメントが非同期ジェネレーターに導入されたと思います:
async for TARGET in ITER:
BLOCK
else:
BLOCK2
PEP 492 によると。
基本的に、これはあなたがすべきことを意味します:
async for number in generate(10):
print(number)
また、 ジェネレーターとの違い も確認してください。
ネイティブコルーチンオブジェクトは、iterおよびnextメソッドを実装していません。したがって、それらを反復したり、iter()、list()、Tuple()やその他の組み込み関数に渡すことはできません。また、for..inループでも使用できません。 iterまたはnextをネイティブコルーチンオブジェクトで使用しようとすると、 TypeErrorで。
これを使用してリストをループして非同期
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