Confused by print(list(...)) seemingly clearing zip object's contents (VScode/jpynb)

I’m doing the medical insurance task at the end of the dictionary module:

I downloaded the jupyter notebook and have been working in vscode (as i have for all the ones you can do that up to now). In the comprehension section I added in an extra print line to make sure I got that cell to output correct from no.9… and now the code in no.10 is coming up blank, unless i comment/remove the print line.

My understanding was that the “list” function doesn’t change the original that is passed in and you have to store the result to keep the changes… but the addition of the print(list(…)) seems to be clearing the contents of the zip? but that doesn’t seem right what am I missing here?

When you use the built in function zip(), it combines (for lack of a better word) two lists & it returns a tuple, which is immutable. So, to print() it, you have to cast it as a list by using the built in list() function.
Lists are mutable.

So, step 9 is like this:

zipped_ages = list(zip(names, ages))

And, in 10, you didn’t write the list comprehension quite right. (you’re close!). You’re creating a dictionary based on items in 2 lists…and matching the name to the age–one will be the key and the other is the value.

names_to_ages = {names:ages for [names, ages] in zipped_ages}


thanks for the reply… that doesn’t address the question.

Why does printing the list of “zipped_ages” result is “zipped_ages” then having no contents?

what is the rest of your code above this step?
How did you do step 9?

Like this?

zipped_ages = list(zip(names, ages))


names = ["Marina", "Vinay", "Connie", "Isaac", "Valentina"]
ages = [27, 24, 43, 35, 52]


zipped_ages = zip(names, ages)


names_to_ages = {key: value for key, value in zipped_ages}

notebook being executed using “run all” on 3.10.8 kernal.
using [, ] in the comprehension doesn’t change the observed behaviour.

zip objects are iterators which are consumed as they are accessed; that is why it is empty.

>>> names = ["Marina", "Vinay", "Connie", "Isaac", "Valentina"]
>>> ages = [27, 24, 43, 35, 52]
>>> z = zip(names, ages)
>>> while True:
...     print (next(z))

('Vinay', 24)
('Connie', 43)
('Isaac', 35)
('Valentina', 52)
Traceback (most recent call last):
  File "<pyshell#10>", line 2, in <module>
    print (next(z))

Even the simple act of printing the zip object will consume it, as does casting it to a list.


Additionally, If it helps, you could also run your code (with that print(list()) part commented out and uncommented) through here:
Which will give you another visual explanation too.

1 Like

Fun fact: An iterable will have an __iter__ attribute; an iterator will have a __next__ attribute. It’s one way we have to distinguish the two.

>>> hasattr([1,2,3,4], '__iter__')
>>> hasattr(zip([1, 2, 3, 4], [9, 8, 7, 6]), '__next__')

We can turn an iterable into an iterator in one fell swoop:

i = iter([1, 2, 3, 4])
while True:
    print (next(i))

Traceback (most recent call last):
  File "<pyshell#24>", line 2, in <module>
    print (next(i))

Loops and Control Flow: That is what algorithms are based upon. Iterators are the way we funnel in data, top to bottom, or left to right, however one wants to see it.

Iterators are an optimization device in that they do not consume memory. The data consumes the memory. If we point an iterator to a block of data, it will not consume that memory. The data is safe. The iterator will only consume a virtual representation of the data, or should we say, realization since the true representation is withheld. We get it piecemeal, one item at a time. But the reference to that data point is forgotten.

1 Like