In this lesson, I’m going to cover the differences between how the
zip() function works in Python 2 and Python 3. So far, I have described—and later in this series, I will continue to describe—the behavior of
zip() in Python 3, because that’s the most recent and widely used family of Python.
The main difference between how
zip() works in Python 2 versus Python 3 is simple—it returns a list of tuples instead of an iterator. Otherwise, it has almost exactly the same behavior and effects. However, this little change can have a dramatic effect on your memory usage if you’re passing in large input iterables to the
00:58 And the reason for this is because a list—when you return a list, you need to construct that entire list and build it and hold it somewhere in memory so that it can be returned, whereas an iterator actually constructs the tuples of the contents of the zipped output in a one-at-a-time fashion, so only one tuple is ever actually being processed at a given time.
Of course you can mimic the Python 2 behavior in Python 3 by just wrapping all of your calls to
zip() with a
list constructor, if for some reason you really need a list. And in fact, that’s what I did in the last lesson.
Just to show you the contents of the
zip() output, I often found it convenient to wrap it in a
list constructor, just because that has more convenient printed output. But remember, if you use this little trick to get a list, then you’ll incur exactly the same—perhaps—downsides if you’re using some really large inputs.
So, keep that in mind, but know that it’s very easy to get a list if you need to in Python 3. The reverse is also true, luckily. It’s not quite as simple, but you can use the
itertools.izip() function in Python 2 to get the same behavior as Python 3’s
And so if I say
zip(fruits, prices) in Python 2, I get—as you can see—a list with three tuples in it, and those tuples correspond to the i-th items from each iterable in the i-th position of the output, right? And if I want to be really careful, I could say
type(zip(fruits, prices)), and as you can see, it is of
<type 'list'>. Now, if you’ll remember from the last little section, I can say
from itertools import izip and if I use
And as you can see, it does exactly what you might expect it to do. This is indeed an iterator that one can iterate through. And I’ll go through this unpacking paradigm a little bit more in the next lesson, but just to show you that it’s not a list but it is still an iterable thing, and it functions in exactly the same way as the
zip() from Python 3.
So, something that I think is kind of fun about this difference—or, kind of a fun way to get around it—is a little trick that you can do to make sure that your usage of
zip() is compatible in both Python 2 and Python 3.
If you’re not sure where or which Python version is going to be run on your code, you can actually do a trick like this, where you can say
from itertools import izip as zip—so, give
izip() the alias
zip—and then you can say
except Error: and then you just say
And what this will do is if
izip() exists, you know that you are in Python 2, because
izip() does not actually exist as a function in
itertools in Python 3, because there’s no need for it. So, if it does exist, you know you’re in Python 2 and you import it as
zip, so you essentially cover up of the original implementation of
zip() with this new name that you’re giving
zip—or, this new function that you are giving the name
zip to, I should say. But if you’re not in Python 2—if you’re in Python 3—this will actually throw an
zip() will indeed still have the Python 3 behavior because nothing happened, right? And so in this case, now I can say
zip(fruits, prices) and I get an
itertools.izip object, which behaves in almost exactly the same way as the Python 3
zip object that it returns in Python 3.
And then if I say
zip(fruits, prices), I get a
zip object which behaves in the same way as the
izip, but if I need to make it look more like the Python 2 behavior, then I can say
list(zip()) and get this list version. And again, I can do this exact same thing where I say
from itertools import izip—and you can see my REPL’s not suggesting anything for me, so that means it doesn’t really exist, but—
import izip as zip.
So, that is how you deal with these kinds of compatibility issues that might arise in Python 2 and Python 3 when you’re trying to use the
zip() function and you want to make sure that you either are getting an iterator or a list, as long as you know that that is in fact what you are getting. In the next lesson, I’m going to cover some ways to actually iterate through parallel iterables and do calculations on them and show why that’s a really useful feature that the
zip() function lets you do.
Become a Member to join the conversation.