Efficient Iterations With Python Iterators and Iterables (Summary)
You’ve learned a lot about Python iterators and iterables. Now you know what they are and what their main differences are. You learned how to create different types of iterators according to their specific behavior regarding input and output data.
You studied generator iterators and learned how to create them in Python. Additionally, you learned how to build your own iterables using different techniques. Finally, you touched on asynchronous iterators and asynchronous loops in Python.
In this video course, you learned how to:
- Create your own iterators using the iterator protocol in Python
- Differentiate iterators from iterables and use them in your code
- Use generator functions and the
yield
statement to create generator iterators - Build custom iterables using different techniques, such as the iterable protocol
- Write asynchronous iterators using the
asyncio
module and theawait
andasync
keywords
With all this knowledge, you’re now ready to leverage the power of iterators and iterables in your code. In particular, you’re able to decide when to use an iterator instead of iterable and vice versa.
Congratulations, you made it to the end of the course! What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment in the discussion section and let us know.
00:00 In the previous lesson, I went full circle returning to interables themselves. In this lesson, I summarized the course and point you at other resources that may be of interest.
00:10
The for
loop in Python works by iterating over an iterable where an interable is any object that defines __iter__
. To iterate over an iterable, you need an iterator, a special object used to track the current position in the iterable and what value gets returned.
00:27
Next in the loop, iterators require two magic methods, __iter__
and __next__
, which together are known as the iterator protocol.
00:37
All iterators are iterable since they define __iter__
, but the reverse isn’t true. Not all iterables have __next__
. For both iterables and iterators, __iter__
returns an iterator, which in the case of an iterable is its associated iterator, and for an iterator, it’s the iterator itself.
01:00
The other part of the protocol is __next__
, which is the method called to get the subsequent item in the iteration. If the iteration is complete, __next__
raises StopIteration
instead of returning a value.
01:15
A generator function is a shortcut for creating iterators. A function becomes a generator by using the yield
keyword inside of it. The value you associate with the yield
keyword is the subsequent item in an iteration, what you’d otherwise return from __next__
in an iterator.
01:32 Unlike regular functions which run to completion, generator functions return without doing anything, responding with a generator iterator. This iterator is then used like any other iterator.
01:44
Python takes care of the __iter__
, and __next__
process by calling the function and using the yielded values.
01:51
In addition to yield
on its own, you can also use yield from
. This is a shortcut for creating generators, which themselves are shortcuts to iterators.
02:01
When you yield from
an iterable, a generator gets created that iterates over that iterable. Another shortcut for creating generators is a generator expression.
02:11 These use syntax almost identical to list comprehensions, but with parentheses instead of square brackets.
02:19
Python has two built-in functions for dealing with iterators: iter()
and next()
. These invoke a class’s underlying __iter__
and __next__
.
02:27
A for
loop starts out by calling iter
on the value given within the in
part of the for
statement. This creates an iterator, which for
then calls next
on in order to get the subsequent value.
02:41
Instead of writing a whole iterator class for your iterable, you can quickly embed one in the __iter__()
method using the built-in iter
function, yield
or yield from
to create inline generators.
02:55
A sequence is a container with directly accessible items like a list or the characters in a string. Sequences are also sliceable. To be a sequence, an object implements the sequence protocol, which consists of __len__
to return the length of the sequence and __getitem__
to return the value at a given index.
03:16
__len__
gets called by the built-in len
function, whereas __getitem__
gets called when you use square brackets on an object.
03:23
Objects that implement the sequence protocol are automatically iterable. Python takes care of this for you, even if you don’t implement __iter__
.
03:33 Here are some resources in case you wish to drill down more on some of the topics covered in this course.
03:39
This tutorial covers how single and double underscore names get used in Python. While this one is specific to __dunder__
methods covering a whole lot of them, there are over a hundred __dunder__
methods that a Python class can use, so there’s lots more to learn in dunderland.
03:55 Although I covered generators quickly, this tutorial and associated course might be of interest to you if you’d like to learn more. And finally, I briefly hinted at the existence of concurrent programming in Python.
04:06
This tutorial and corresponding course teach you all about the async
and await
keywords along with the asyncio
library.
04:13 Put your thinking caps on for this one. Parallel programming can get messy. That’s all from me. I hope this course gave you a deeper understanding of iteration in Python.
Become a Member to join the conversation.