filter object becomes empty after iteration?

I am learning how to use a function filter

.

This is the code I wrote:

people = [{'name': 'Mary', 'height': 160},
          {'name': 'Isla', 'height': 80},
          {'name': 'Sam'}]

people2 = filter(lambda x: "height" in x, people)

      

As you can see, I am trying to delete all dictionaries that do not contain a key 'height'

.

The code works correctly, in fact, if I do:

print(list(people2))

      

I get:

[{'name': 'Mary', 'height': 160}, {'name': 'Isla', 'height': 80}]

      

The problem is, if I do this twice:

print(list(people2))
print(list(people2))

      

the second time, I get an empty list.

Can you explain to me why?

+3


source to share


2 answers


This is the classic python3 doh !.

A filter is a special iterable that you can iterate over. However, as a generator, you can only iterate over it once. So, by calling list(people2)

, you iterate over each element of the object filter

to generate list

. At this point, you've reached the end of the iteration and haven't returned anything else.

So when you call again list(people2)

, you get an empty list.



Demo:

>>> l = range(10)
>>> k = filter(lambda x: x > 5, l)
>>> list(k)
[6, 7, 8, 9]
>>> list(k)
[]

      

I should mention that with python2, it filter

returns a list, so you don't face this problem. The problem occurs when you inject py3 lazy evaluation into the image.

+8


source


This is because the filter actually turns into an iterator. This iterator doesn't really do anything until you start using its results, in this case when you send it to a list. people2

is what is ready to filter the list of people, and then when the list is called on it, it iterates over the list of people and passes the filtering result. Now that the iterator is complete, it has nothing to iterate over, so when you call the list on it a second time, there is nothing there.



Read this for more details - lazy evaluative python

+1


source







All Articles