2009-08-26 5 views
5

Per esempio, supponiamo faccio questo:È una buona idea hash una classe Python?

>>> class foo(object): 
...  pass 
... 
>>> class bar(foo): 
...  pass 
... 
>>> some_dict = { foo : 'foo', 
... bar : 'bar'} 
>>> 
>>> some_dict[bar] 
'bar' 
>>> some_dict[foo] 
'foo' 
>>> hash(bar) 
165007700 
>>> id(bar) 
165007700 

Sulla base di ciò, sembra che la classe è sempre un hash come il suo numero di identificazione. Pertanto, non dovrebbe esserci alcun pericolo di preoccuparsi, ad esempio, di un hashing bar come valore foo o bar o di hash che cambiano se muto la classe.

Questo comportamento è affidabile o ci sono dei trucchi qui?

risposta

8

Sì, qualsiasi oggetto che non implementa una funzione __hash__() restituirà il proprio ID quando hash. Da Python Language Reference: Data Model - Basic Customization:

classi definite dall'utente hanno __cmp__() e __hash__() metodi per impostazione predefinita; con loro, tutti gli oggetti vengono confrontati in modo disuguale (eccetto che con se stessi) e x.__hash__() restituisce id(x).

Tuttavia, se si desidera disporre di un identificativo univoco, utilizzare id per chiarire l'intento. Un hash di un oggetto dovrebbe essere una combinazione degli hash dei suoi componenti. Vedi il link sopra per maggiori dettagli.

+2

Qualsiasi classe il cui * metaclass * non abbia una funzione __hash __(). –

+0

Va notato che sebbene questo sia nella pagina "cosa c'è di nuovo per Python 2.6", questo comportamento sembra funzionare per me in Python 2.4. –

+1

@Jason Ho cambiato il riferimento alla documentazione generale. –

6

Le classi hanno implementazioni predefinite di __eq__ e __hash__ che utilizzano id() per effettuare confronti e valori di hash di calcolo, rispettivamente. Cioè, si confrontano per identità. La regola principale per l'implementazione dei metodi __hash__ è che se due oggetti si confrontano l'uno con l'altro, devono anche avere lo stesso valore di hash. I valori di hash possono essere visti come una semplice ottimizzazione utilizzata da dicts e set per trovare oggetti uguali più velocemente. Di conseguenza, se si modifica __eq__ per eseguire un diverso tipo di test di uguaglianza, è necessario modificare anche l'implementazione __hash__ per concordare con tale scelta.

Le classi che utilizzano l'identità per il confronto possono essere liberamente mutate e utilizzate in dts e insiemi perché la loro identità non cambia mai. Le classi che implementano __eq__ per confrontare per valore e consentire la mutazione dei loro valori non possono essere utilizzate nelle raccolte hash.