Python › Async Generators & Async Context Managers

How would you implement a custom async iterator class from scratch, without using an async generator function?

Advanced

Answer

Implement __aiter__ (returning self) and __anext__ (an async method that returns the next value or raises StopAsyncIteration when exhausted) — this is the lower-level protocol that async generator functions are automatically compiled down to by the interpreter.
class AsyncCounter:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0
    def __aiter__(self):
        return self
    async def __anext__(self):
        if self.current >= self.limit:
            raise StopAsyncIteration
        await asyncio.sleep(0.01)
        self.current += 1
        return self.current
Real-world example Building a custom async iterable class with more control than an async generator function provides, like exposing extra methods or state.

Common follow-ups: Why would you choose to write a full __aiter__/__anext__ class instead of a simpler async generator function?