Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Functions: Iterables and Iterators

Give Feedback

00:01 Iterables and Iterators. This section is going to look at functions you can use with iterables and iterators. The first one is going to be len(), which tells you the length of the iterable that you pass it.

00:18 Here’s a list filled with some random-ish numbers. Looking at len(a) shows us there are 9 elements within that list. We can see that that list does indeed have nine elements. Next up, any() and all().

00:36 any() and all() work on the Boolean values of the iterables that you pass to them. As we’ve seen earlier, any entry can be considered to be True or False, but to simplify matters, the three lists are going to explicitly use True or False. So in the case of a, all three entries are True.

00:58 In the case of b, some of the entries are True but it has a False present as well.

01:08 And the third list will have all False values. So these are the three possibilities which are present.

01:19 If we look at any(), we can see that any(a) is True because some of them are True. In fact, all of them are True. If we look at any(b), that’s also True because it has some True values even though they’re not all True.

01:36 Looking at any(c) gives us the result False because none of them are True.

01:45 The partner of this is all(). If we look at all(a), because they’re all True we get True, as you can see here.

01:55 all(b) gives us False, because not all of them are because we have one False value there. And as you can imagine, for all(c) we also get False because there are no True values, let alone all of them being True.

02:16 For the next section, we’re going to define a variable d as a list of numbers. As you can see, it has nine elements in it.

02:30 Let’s look at the reversed() function. If we define e as reversed(d), we’d hoped to get that list out backwards, and if we look at it, we don’t get exactly what we’re expecting.

02:43 What you may have been expecting is a reverse version of that list, and instead we get a reverse iterator object. Now, most of the time in your code, that will be okay, but some of the time you may want to see that list—for instance, when you’re debugging or printing it out. So if we do list(e), you can see that list is d in reverse.

03:04 But that works how you probably expect, and sometimes you will need to do this, but often within your code, you won’t need to do this because Python will deal with the iterator.

03:15 Instead of casting all of this to a list in one go and outputting it, Python will do it in a more efficient manner and only produce the value which is needed when they’re needed.

03:26 The analogy I can think of is imagine having a machine which could produce cars for you. You’d have two modes it could operate in—one where it produces all the cars you need in one go, and one where it does them on demand.

03:40 That would be fine if you only needed one, but if you needed 3 million of them, you’d need to find somewhere to store them all. In this case, it’s storing all those numbers in memory, and it takes time to create them.

03:52 Generally, Python’s create-on-demand system is a more efficient way for it to work and has much lower memory demands, but sometimes dealing with this when you’re starting out means you need to cast things into a list to understand what’s happening behind the scenes. With that out of the way, let’s look at sorted(). Here we’re defining f as the sorted version of d.

04:13 If we look at f, it works the way we’d expect—it produces a list and it’s the elements of d here which have been sorted. And see, we’ve got two 7s, which is why we’ve got two 7s there.

04:27 This list is exactly as we’d expect. And it’s also possible to reverse sorted() if you need it to be that way around.

04:37 Next up, let’s look at range(). Now, range() is really useful. You may have already encountered it. If we enter range() here in the REPL, we get this range from 0 to 10, which isn’t that helpful because it doesn’t really tell us what’s going on, but if we cast that into a list, we can see we get the values 0 to 9.

05:00 Remember, it’s not including this final number, so it’s 0 to 9we get 10 in total. It’s possible to pass it explicitly the start and end values, and also a third value, stride.

05:14 Here we can see a range(0, 10) with a stride of 2. That gives just the even numbers, 0 to 8, and again, it doesn’t include the last number. range() is extremely useful and you’ve probably used it already, but you may not have heard of these last two, zip() and enumerate(), which are easier to understand in the context of a program, so we’re going to switch over to code now.

05:40 Iterables and Iterators: enumerate(). As a demonstration of this, a simple program is going to be created which is going to print out the list of players of an imaginary team.

05:55 A typical thing, we have a list here and I’m going to create a for loop. for player in players: print(player). Fairly piecemeal stuff, and you’ve probably seen something like this before.

06:08 If we see that in action, it works exactly as we’d expect, printing each name on its own line. But quite often it’s important to know which number on the list is which index in the list. The way you would probably do this if you weren’t aware of enumerate() is to create a count variable which is initialized before the loop starts.

06:31 We’ll print the count as well as the player out on each line, and then after that, the count gets incremented with count += 1, and that’ll work just fine as we can see here.

06:43 But Python provides us with enumerate(), which makes a much cleaner way to do this same functionality. We’re going to delete the count variable, we’re going to delete the increment of count, and then we’re going to wrap players in the enumerate() function, which outputs two things. It outputs the normal player, but it will also output the count—a zero-indexed counter of the number of times a loop has run. So we have much neater code, you don’t have to worry about initializing or incrementing the count variable—which everyone has forgotten at some point—and running the code gives us exactly the same output as before, but it’s a much neater piece of code to read.

07:24 It’s easy to see exactly what’s happening, and because it’s standard code, you’ll get used to seeing this and understand it intuitively every time.

07:38 Iterables and Iterators: zip().

07:42 In this example, you have two lists which need to be paired together—so in this case, a list of three countries,

07:57 and one which is continents which go with them.

08:07 You’ll want to create tuples with these paired together. The way you would initially do this would probably involve a for loop, so in this case, using an index variable combining range() and the len() of the countries list.

08:23 That index will now allow us to access the countries[i] and continents[i].

08:36 You can check if that works by running the program,

08:41 and as you can see, they’ve been paired correctly: 'France' with 'Europe', 'Tanzania' with 'Africa', 'Canada' with 'North America'.

08:49 Now that we know we’re accessing those correctly, we can put these together. So first things first, let’s create a list for them to go in. Here’s our empty merged list,

09:04 and then we can do merged.append() and put that in brackets inside there so we create a tuple with those two together.

09:15 Finally, we can print out the merged list, and now we can see that running and we have our list with the appropriately paired countries and continents.

09:29 If you’re not aware of the zip() function, this is probably the kind of thing you would do many times. For there’s a much simpler way to do this, and as we can see, we can use merged_2, it uses the zip() function with those two lists countries and continents, and that’s that entire for loop replaced.

09:51 When we run this, they both produce identical output, but this is a much more complicated equivalent to this. The zip() part is much simpler than these three lines where you create an empty list and a for loop. It could have been done with a list comprehension but still would have been complicated. But zip() works faster, is much easier, and is much less error-prone than the manual approach.

10:17 It’s important to remember that this is a zip in terms of a zipper on your clothes, not in terms of a compressed file creator. zip() is incredibly useful whenever you have lists you need to merge together.

10:30 Iterables and Iterators: iter() and next(). The last thing we’re going to look at in this section is the creation of an iterator such as we saw earlier on. It’s possible to create an iterator using any iterable. We’re going to use a list in this example.

10:47 It has a method next(), which pops the next value off of that iterator until it’s exhausted, when you’ll get a StopIteration exception. Let’s make an example now, so here a = iter() and we’re just going to pass it a list directly of [1, 2, 3, 4, 5, 6], to keep it nice and simple.

11:12 Now we’ve created our iterator a and now we can just use next(a) and we get the next value from it, and then 2, 3, 4, 5.

11:21 And once it’s exhausted, if we try next() again, we get a StopIteration exception. This is the way that any iterable works behind the scenes with Python, so anything which can take an iterator will work exactly the same way with an iterator you’ve created using the iter() keyword.

alanhrosenthal on March 21, 2020

Very complete. Very easy to understand.

Well Done!

Mahesh on March 25, 2020

getting below error for ZIP.py <zip object at 0x00633F80>

peterabbeel on March 29, 2020

Related to above comment:

getting below error for ZIP.py <zip object at 0x00633F80>.

Note this is not an error.

print(merged_2) returns the memory address of the iterator merged_2 print(list(merged_2)) returns the content of the iterator merged_2

You can also call the zip functionality as following:

print(list(zip(countries, continents)))

Cory on April 24, 2020

Exactly what peterabbeel did on <zip object at 0x036B4F08> I also had to switch mine to print(tuple(merged_2) which then gave me the proper output although it makes it immutable. Still learned a ton from this tutorial.

Alain Rouleau on Aug. 7, 2020

I didn’t even know some of these functions existed such as any() and all(). Of course everybody should already know about them since their just built-in functions. But very handy.

Learned quite a lot from this video, thanks.

leroygcooper on Nov. 26, 2020

Hey Darren. In the zip function example using the “merged” for-loop, were there two sets of brackets around the “merged.append…” line due to the argument being a tuple (countries[i], continents[i])?

Bartosz Zaczyński RP Team on Nov. 26, 2020

@leroygcooper That’s correct. You need to wrap both elements in a tuple because the list’s .append() method expects only a single item, and we want the list to contain pairs.

Become a Member to join the conversation.