zhaoL zhaoL - 7 months ago 7
Python Question

What's the difference between these two implementation?

Assume I have a list 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 sublist of
S
, and then output that list or return
None
id
x
is not found.

(Note: the intersection of any two of the sublists is empty, 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 write it like this:

def find(x):
try:
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)

Answer

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.

Comments