2012-08-15 15 views
8

Per i contenitori built-in Python (list, tuple, ecc) l'operatore in equivale a any(y == item for item in container) con l'avvertenza che il primo metodo è più veloce (e più bella):Gli elenchi Python hanno un equivalente per __contains__ che verifica l'identità?

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 

c'è un equivalente per any(y is item for item in container) ? Cioè, un test che usa is invece di ==?

risposta

6

No, non c'è. L'operatore is non è semplicemente necessario che spesso giustifichi la necessità di mantenere un metodo ottimizzato per C e di aggiungere confusione all'API python.

Il test in per elenchi e tuple fa una ricerca completa simile a any, anche se in C, btw. In insiemi, tuttavia, il test utilizza l'efficiente algoritmo di archiviazione sottostante al contenitore e la ricerca impiega un tempo costante nel caso previsto. Per entrambi gli insiemi e le mappature, si suppone che le chiavi abbiano un hash stabile, il che nella maggior parte dei casi significa che is non dovrebbe essere necessario, in realtà.

Così, l'ortografia corretta è:

# 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

In realtà, ho sempre considerato un difetto di documentazione che i metodi '' list.index' e list.count' ecc dicono qualcosa per l'effetto " Restituisce l'indice nell'elenco del primo elemento il cui valore * è * x È un errore se non esiste tale elemento " – mgilson

+0

Ma anche con i set,' in' controlla il valore hash che non * garantisce * che il gli oggetti sono distinti. considera 'a = (1,2,3); c = (1,2,3); c è un; s = set ([a]); c in s'. Anche se, al momento, non riesco a pensare a un momento in cui ciò sarebbe importante. – mgilson

+0

No, sottolineando che l'operatore 'in' su set e dict non ha * do * una scansione. –