Today I learned that generators support membership testing with the operator
Membership testing in Python boils down to using the operator
in, as the REPL session excerpt shows:
>>> my_list = [42, 73, 16, 0, 10] >>> 42 in my_list True >>> 43 in my_list False >>> 10 in my_list True
What I hadn't realised yet is that generators also support membership testing! It is very easy to verify that they do support membership testing, though:
def generator(): yield 42 yield 73 yield 16 yield 0 yield 10 gen = generator() print(42 in gen) # True
What I immediately realised afterwards is that you need to be very careful about membership testing with generators. For example, consider the generator function from before:
def generator(): yield 42 yield 73 yield 16 yield 0 yield 10
We can check if the number 999 is in there and we will get the correct answer:
>>> gen = generator() >>> 999 in gen False
But now, think about it.
How can Python tell that 999 is not inside the generator
It had to iterate over it, which means it had to go through all the
yield expressions already!
In turn, this means that the generator was already exhausted.
It is already empty:
>>> next(gen) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
In practice, if a generator reports that a given value is not in the generator, then it is probably because of this issue; because you had already iterated past the value that you were looking for.
Let me show you another example of this:
>>> def generator(): ... yield 1 ... yield 2 ... yield 3 ... >>> gen = generator() >>> 999 in gen False >>> 1 in gen False >>> 2 in gen False >>> 3 in gen False
This example might look obvious to you because I am using a non-existing value to exhaust the generator. However, this issue can also arise after successful membership tests:
>>> def generator(): ... yield 1 ... yield 2 ... yield 3 ... >>> gen = generator() >>> 2 in gen True >>> 1 in gen False
To make sure you understand what's going on, try to guess the output of the three membership checks below. Other than that small challenge, that's it for now! Stay tuned and I'll see you around!
>>> def generator(): ... yield 1 ... yield 2 ... yield 3 ... >>> gen = generator() >>> 3 in gen # ??? >>> 1 in gen # ??? >>> 2 in gen # ???
That's it for now! Stay tuned and I'll see you around!
If you enjoyed this blog article, you will love the mathspp insider 🐍🚀 newsletter! Join +16.000 others who are taking their Python 🐍 skills to the next level! 🚀