9

For the built-in python containers (list, tuple, etc) the in operator is equivalent to any(y == item for item in container) with the caveat that the former method is faster (and prettier):

In [13]: container = range(10000)
In [14]: %timeit (-1 in container)
1000 loops, best of 3: 241 us per loop
In [15]: %timeit any(-1 == item for item in container)
1000 loops, best of 3: 1.2 ms per loop

Is there an equivalent to any(y is item for item in container)? That is, a test that uses is instead of ==?

ChrisB
  • 4,628
  • 7
  • 29
  • 41

1 Answers1

7

Nope, there isn't. The is operator is just not needed that often to justify having to maintain a C-optimized method and adding confusion to the python API.

The in test for lists and tuples does do a full search similar to any, albeit in C, btw. In sets however, the test makes use of the efficient storage algorithm underlying the container and the search takes constant time in the expected case. For both sets and mappings, keys are supposed to have a stable hash, which in most cases means is should not be needed, really.

So, the correct spelling is:

# For sequences
any(y is item for item in container)

# For sets, short circuit first for the not-present case:
# (note that you normally should not need this as you are supposed to rely on the hash)
y in setcontainer and any(y is item for item in setcontainer)

# For mappings, y is a key
y in mapping 

# For mappings, y is a value, and you do not have a key, fall back to any
any(y is item for item in mapping.itervalues())
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 5
    In fact, I've always considered it a documentation flaw that the methods `list.index` and `list.count` etc say something to the effect "Return the index in the list of the first item whose value *is* x. It is an error if there is no such item" – mgilson Aug 15 '12 at 14:40
  • But even with sets, `in` checks the hash value which doesn't *guarantee* that the objects are distinct. consider `a=(1,2,3); c=(1,2,3); c is a; s = set([a]); c in s`. Although, currently, I can't think of a time where this would matter. – mgilson Aug 15 '12 at 14:47
  • Nope, just pointing out that the `in` operator on sets and dicts doesn't have *do* a scan. – Martijn Pieters Aug 15 '12 at 14:49
  • Thanks for the nice summary. I find it a little unfortunate that "`is` is just not needed that often" -- it would be nice to have something semantically tighter than `any` + a generator. And, like mgilson points out, there are several places in the documentation where the distinction between `==` and `is` is glossed over. But I guess not *everything* can be maximally concise in python :). – ChrisB Aug 15 '12 at 15:13