zhaoL zhaoL - 6 months ago 6x
Python Question

What's the difference between the two implements?

Assume I have an array of lists

S = [ list1, list2, ...]

and I want to write a function find() such that for an input x, the function will look for whether x is in some list of S, and then output that list; or it will return None.
(the intersection of any two of the lists are empty-set, so at most one list will be found.)

My code is very straightforward:

def find(x):
for L in S:
if x in L:
return L
return None

But I have seen someone wrote it like this:

def find(x):
return next( L for L in S if x in L)
except StopIteration:
return None

I wonder what's the differences between the two codes? Is the second one more preferred than the first?( for example, from a software project viewpoint)


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.