2012-03-24 9 views
10

Diciamo che avere un set:Set Popping (Python)

foo = {1, 2, 3, 4, 5} 

Nel libro Attualmente sto leggendo, Pro Python, si dice che l'uso foo.pop() apparirà un numero arbitrario da quella selezione. MA ... Quando lo provo, è pops 1, then 2, then 3... Lo fa arbitrariamente, o è solo una coincidenza?

+0

Questo ha a che fare con la funzione di hash che usa un set per mappare il suo contenuto di posizioni nella memoria. Prova a fare 'hash()' su diversi tipi di dati e vedere quali numeri ottieni. Il numero arbritrario estratto da un set _will_ è l'elemento _next_ nel set. Si dà il caso che "l'ordine" memorizzato nel set non possa essere ordinato n_necessariamente per quanto ti riguarda. In questo esempio, l'ordine in cui gli elementi si verificano coincidono con l'ordine in cui l'hashmap è memorizzata/recuperata. –

+0

Ho trovato la stessa cosa oggi e voglio sollevare la tua domanda –

risposta

16

Il motivo per cui è arbitrario è perché non esiste la garanzia in merito all'ordine in cui verrà visualizzato. Dato che hai appena creato il set, è possibile che gli elementi siano memorizzati in un ordine "carino", e quindi .pop() si verifica per restituirli in tale ordine, ma se si dovesse modificare il set, questo potrebbe non continuare a essere mantenuto.

Esempio:

>>> foo = set() 
>>> foo.add(-3) 
>>> foo.add(-1) 
>>> foo.add(2) 
>>> foo.pop() 
2 
>>> foo.pop() 
-3 
14

Set e dizionari sono realizzati tramite le tabelle hash. Sono raccolte non ordinate, il che significa che non hanno un ordine garantito.

L'ordine visualizzato è un dettaglio di implementazione non garantito. Nel CPython, il valore hash per un intero è il numero intero in sé:

>>> [hash(i) for i in range(10)] 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

Questo dettaglio di implementazione fa sì che gli interi ad apparire ordinata nel set. Altri set sarebbero semi-ordinati, {5, 6, 7, 8, 9} appare come set([8, 9, 5, 6, 7]).

Al contrario, altri tipi di dati come str hanno diverse funzioni hash e sembreranno più confusi. Per esempio:

# Example of scrambling str objects in a 64-bit build 
>>> {'red', 'green', 'blue'} 
set(['blue', 'green', 'red']) 

Il metodo set.pop salta fuori le voci da sinistra a destra. Anche questo è un dettaglio di implementazione non garantito.

La risposta breve alla tua domanda è Sì, l'ordine è arbitrario ma No, ciò che hai visto non era solo una coincidenza, piuttosto era un dettaglio di implementazione non garantito interessante.

Spero che questo cancella-up il mistero per voi :-)