Assume I have a list of lists
S = [list1, list2, ...]
find
x
x
S
None
x
def find(x):
for L in S:
if x in L:
return L
return None
def find(x):
try:
return next( L for L in S if x in L)
except StopIteration:
return None
The difference is that the second version constructs a generator that yields items from the list S
if you can find x
in that item.
Then it tries to return the first object that's yielded from that generator by calling next
on it.
Conceptually, there's really not much difference between the two snippets, note how they both employ for L in S
-> if x in L
, the first one as a traditional for
loop with an if
statement in its body, the second one in the form of a comprehension. Both versions are lazy, that is they return immediately when a match is found.
I think your code is perfectly fine. The second one could use a default value to avoid the manual exception handling, i.e.
return next((L for L in S if x in L), None)
which tries to return the first item yielded by the generator, or None
if there's no such item. Is it worth it to construct a generator that is supposed to yield a single item here, and is it more readable? I'd say "probably not" in my opinion.