object.__aiter__(self)
object.__anext__(self)
💡 Summary: Python’s __aiter__()
and __anext__()
methods are used to implement an asynchronous for loop (keywords: async for
). In contrast to a normal (synchronous) for loop, an asynchronous for loop iterates over an asynchronous source.
__aiter__()
returns an asynchronous iterator object (in many cases it’s simply a reference to itself: return self)__anext__()
returns the next element—could be obtained from an asynchronous source such as an asynchronous database. But doesn’t have to be!
We call these “Dunder Methods” for “Double Underscore Methods” (also called “magic methods”). To get a list of all dunder methods with explanation, check out our dunder cheat sheet article on this blog.
⚡ Attention: A common misconception of async for
is to assume that it iterates over the loop iterations in parallel. This is not the case. The async for
iterates over an asynchronous source (e.g., if you iterate over database entries that may arrive asynchronously from user inputs). A synchronous for loop cannot do this.
Let’s dive into an example next!
Example Asynchronous Iterator
import asyncio class Asynchronous_Iterator: ''' Iterate over an asynchronous source. n Iterations.''' def __init__(self, n): self.current = 0 self.n = n def __aiter__(self): return self async def __anext__(self): await asyncio.sleep(1) print(f"get next element {self.current}") self.current += 1 if self.current > self.n: raise StopAsyncIteration return self.current - 1 async def main(): async for i in Asynchronous_Iterator(3): print(f"next element {i}") asyncio.run(main())
Output:
get next element 0 next element 0 get next element 1 next element 1 get next element 2 next element 2 get next element 3
- The
AsynchronousIterator
object implements the dunder methods__iter__()
and__next__()
. - You use it in an asynchronous for loop like so:
async for i in Asynchronous_Iterator(3)
- The output shows that the iterations are performed synchronously, i.e., we first finish the execution of one loop iteration before starting the next!
💡 Note: Many people would expect the output to be like this—assuming Python first starts all loop iterations at the same time and then executing them in parallel:
# NOT THE OUTPUT! get next element 0 get next element 1 get next element 2 get next element 3 next element 0 next element 1 next element 2
But this is not the case! Again, async for
iterates over an asynchronous source, it is not a parallel for loop!
Background __iter__() and __next__()
The Python __iter__()
method returns an iterator object. An iterator object is an object that implements the __next__()
dunder method that returns the next element of the iterable object and raises a StopIteration
error if the iteration is done.
The Python __next__
method returns an arbitrary element that represents the “next” element when you iterate over the object on which it is called. For example, if you iterate over my_object
using for x in my_object
, Python internally calls my_object.__next__()
in each loop iteration to determine the next element.
In the following example, you create a custom class Data
and overwrite the __init__()
, __iter__()
, and __next__()
methods so that you can create your own iterator over a Data
object.
class Data: def __init__(self, data): self.data = data # an iterable def __iter__(self): self.current_index = 0 return self def __next__(self): if self.current_index < len(self.data): x = self.data[self.current_index] self.current_index += 1 return x raise StopIteration
__init__()
initializes the data attribute that is expected to be an iterable.__iter__()
returns the iterator object — the one that implements the__next__()
method. In our case, this is the Data object on which it is called itself. We initializecurrent_index
with zero, so we start iterating with the first index ofdata
.__next__()
returns the next value after one iteration. We increment thecurrent_index
attribute to keep track of the current index of the element indata
.
Let’s create a Data
object d
and an iterator over the data object using the built-in iter()
function (that internally calls __iter__()
)—and start iterating over the object using the built-in next()
function (that internally calls __next__()
):
d = Data([1, 'Alice', 42, 'finxter']) # Create an iterator iterator = iter(d) # Dynamically generate the next values - iterate! print(next(iterator)) print(next(iterator)) print(next(iterator)) print(next(iterator)) print(next(iterator))
The output is as follows: The first four calls result in the expected elements of the data attribute, i.e., 1
, 'Alice'
, 42
, and 'finxter'
. The fifth call of next()
results in a StopIteration
error because we have finished iterating over all elements.
1 Alice 42 finxter Traceback (most recent call last): File "C:\Users\xcent\Desktop\code.py", line 34, in <module> print(next(iterator)) File "C:\Users\xcent\Desktop\code.py", line 14, in __next__ raise StopIteration StopIteration
References:
- https://www.python.org/dev/peps/pep-0525/
- https://stackoverflow.com/questions/38031066/implementing-an-asynchronous-iterator
- https://stackoverflow.com/questions/56161595/how-to-use-async-for-in-python
- https://stackoverflow.com/questions/62226345/using-aiter-and-anext-in-a-collections-abc-coroutine-subclass-to-add-fun
Where to Go From Here?
Enough theory. Let’s get some practice!
Coders get paid six figures and more because they can solve problems more effectively using machine intelligence and automation.
To become more successful in coding, solve more real problems for real people. That’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?
You build high-value coding skills by working on practical coding projects!
Do you want to stop learning with toy projects and focus on practical code projects that earn you money and solve real problems for people?
🚀 If your answer is YES!, consider becoming a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.
If you just want to learn about the freelancing opportunity, feel free to watch my free webinar “How to Build Your High-Income Skill Python” and learn how I grew my coding business online and how you can, too—from the comfort of your own home.