2012-11-21 15 views
6

Sto provando a creare una funzione di hashing personalizzata per le stringhe. Voglio hash stringhe in base alla loro frequenza di carattere in base al peso. In modo che hi e ih generano lo stesso hash. Posso eseguire l'override di __hash__?Stringa di override Python __hash__

Oppure sta creando una classe wrapper che contiene la stringa e sovrascrive __hash__ e __eq__ nell'unico modo?

+0

Vorrei usare la classe wrapper. È simpatico ed esplicito e non causerà confusione fingendo di essere una stringa, ma ha un hash completamente diverso. – millimoose

+0

@millimoose buon punto – darksky

+1

Mescolare 'str' e' custom_str' in un contenitore che usa hash come chiavi potrebbe essere interessante :) –

risposta

4

Si desidera un tipo derivato con diversa semantica dell'uguaglianza. Di solito l'approccio adottato sarà quello di definire come funziona l'uguaglianza, quindi costruire il metodo hash dalle strutture derivate, poiché è necessario che l'hash sia d'accordo con l'uguaglianza. Quello potrebbe essere:

import collections 

class FrequencyString(str): 
    @property 
    def normalized(self): 
     try: 
      return self._normalized 
     except AttributeError: 
      self._normalized = normalized = ''.join(sorted(collections.Counter(self).elements())) 
      return normalized 

    def __eq__(self, other): 
     return self.normalized == other.normalized 

    def __hash__(self): 
     return hash(self.normalized) 
+1

Suppongo di aver creato una funzione gratuita che restituisca un hash. Come inserirò quella chiave nella posizione hash restituita? 'Dict = {}, dict [5] = valore' inserisci' valore' nella posizione 5, o nel tasto '5'? – darksky

+0

posizionare valori in dicts * fa * implica cambiare la semantica dell'uguaglianza, questo è il modo giusto per farlo. Si potrebbe alternativamente strutturare il wrapper come una busta, che ha la stringa originale come attributo di istanza. – SingleNegationElimination

0

L'ipotesi è corretta, non è possibile sovrascrivere le basi in Python. Anche se, naturalmente, è possibile ignorare ciò che farà str(), non funzionerà per i valori letterali stringa.

Se si scrive codice per pre-python 2.2 un'occhiata alla classe UserString se si desidera creare il proprio: http://docs.python.org/2/library/userdict.html#module-UserString

Altrimenti si può semplicemente ereditare str o unicode

Nel tuo caso semplicemente sovrascrivendo il Il metodo __hash__ è sufficiente se si desidera utilizzarlo come tasto dict. Ma se stai guardando il confronto di quanto sarebbe necessario sovrascrivere __eq__ o __cmp__

+0

Argghghh - no, no e no a 'UserString' - è una storia antica - eredita da' str' come 'class mystr (str): ...' –

+0

Dice che se non ho bisogno di supportare la retrocompatibilità per le versioni prima della 2.2, posso semplicemente creare una sottoclasse direttamente dal built in 'str'. Come si farebbe? Sarebbe semplicemente: 'class wrapper_class (str):'? Sarebbe sufficiente sovrascrivere '__hash__' e' __eq__'? – darksky

+0

@JonClements hai appena risposto la prima parte del mio commento :) Che dire dei metodi prioritari? Sarebbero sufficienti '__hash__' e' __eq__'? – darksky

0

è possibile ereditare da str, ma dal momento che questi sono immutabili bisogna sottoclasse loro in un modo leggermente diverso. Molto probabilmente vorrete crearne di nuovi dalle stringhe esistenti, quindi dovete anche sovrascrivere il metodo __new__. Potrebbe anche essere necessario inserire metodi speciali per sconfiggere le ottimizzazioni eseguite da Python.

Questo è un esempio di subclassing str incorporato, l'oggetto mapstr che consente di sostituire facilmente segnaposti nei moduli.

+0

Puoi spiegare cosa intendi con "Molto probabilmente vorresti crearne di nuovi da stringhe esistenti"? Voglio solo creare una stringa che posso passare in '__init__', quindi perché avrei bisogno di sottoclasse' __new__'? Cosa succede se non lo faccio? – darksky

+0

Quindi, come pensi di usarlo? – Keith

+0

Stringhe di hash che hanno gli stessi caratteri in una chiave. Il valore è un elenco di tutte le stringhe. La chiave è una versione ordinata di loro. – darksky