2012-08-15 9 views
8

Para los contenedores incorporados en Python (list, tuple, etc.) el operador in es equivalente a any(y == item for item in container) con la advertencia de que el primer método es más rápido (y más bonita):¿Las listas de Python tienen un equivalente para __contains__ que prueba la identidad?

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 

¿Hay un equivalente a any(y is item for item in container) ? Es decir, una prueba que usa is en lugar de ==?

Respuesta

6

No, no lo hay. El operador is simplemente no es necesario para justificar el mantenimiento de un método C-optimizado y la confusión de la API de Python.

La prueba in para listas y tuplas hace una búsqueda completa similar a any, aunque en C, por cierto. Sin embargo, en los conjuntos, la prueba utiliza el algoritmo de almacenamiento eficiente subyacente al contenedor y la búsqueda toma tiempo constante en el caso esperado. Para ambos conjuntos y asignaciones, se supone que las claves tienen un hash estable, que en la mayoría de los casos significa is no debería ser necesario, realmente.

Por lo tanto, la forma correcta es:

# 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()) 
+5

De hecho, siempre me he considerado un defecto de la documentación que los métodos '' list.index' y list.count' etc dicen algo en el sentido " Devuelva el índice en la lista del primer elemento cuyo valor * es * x. Es un error si no existe tal artículo " – mgilson

+0

Pero incluso con conjuntos,' in' verifica el valor hash que no * garantiza * que el los objetos son distintos considere 'a = (1,2,3); c = (1,2,3); c es a; s = set ([a]); c en s'. Aunque, actualmente, no puedo pensar en un momento en el que esto importe. – mgilson

+0

No, solo indica que el operador 'in' en sets y dicts no tiene * do * scan. –

Cuestiones relacionadas