views:

124

answers:

1

Hello!

I have a bunch of lists of strings and I need to know if an string is in any of them so I have to look for the string in the first list, if not found, in the second, if not found, in the third... and so on.

My question is: What is faster?

if (string in stringList1):
    return True
else:
    if (string in stringList2):
        return True
    # ... #

and so on or using the index() function inside a try / except block?

try:
    return stringList1.index(string) >= 0
except:
    try:
        return stringList2.index(string) >= 0
    except:
       # ... #

I know the "in" is linear and that usually the python recommendations are "better say sorry than ask for permission" (meaning the second approach would be better) but I'd like to know the opinion of someone more qualified :)

Thank you!

+11  A: 
  1. in is the correct way to determine whether something is or is not in a container. Don't worry about speed microoptimization until you have tested your app, found it to be slow, profiled, and found what's causing it. At that point, optimize by testing (the timeit module can be good for this), not by taking the words of internet weirdos.

    If you are doing lots of containment checks you probably want to use a set instead of a sequence; sets have O(1) lookup. If this is not suitable to your problem, you might want to use a list and the bisect module, which still offers algorithmic performance benefits over the O(n) sequence operations.

  2. There's a chance what you really mean if any(string in s for s in iterable_of_string_lists) or if string in string_list_1 or string in string_list_2. Nesting ifs is not quite the nicest way to do an operation like you show.

  3. Never ever ever use a bare except:. Always catch a specific exception, in this case except ValueError. Using except: will catch and ignore all kinds of exceptions you don't intend, like a KeyboardInterrupt if the user tries to exit your app or a NameError if you have a typo.

Mike Graham
+1. Can't have said better.
Xavier Ho
Agree, good answer. I'd also add that from the looks of it the if/else's could be combined into one expression... if (string in stringlist1 or string in stringlist2) etc.
derivation
Thx! This is much more than I expected :DI'd like to use the 2nd option. Looks very "elegant" but I'm afraid I don't have a list of lists... They are different variables...
BorrajaX
@BorrajaX, (2) is complementary, not instead-of, the others. You could spell the "any" solution as `any(string in s for s in [strings_1, strings_2])`, but I probably wouldn't do that myself if there are only two such lists.
Mike Graham