Topic: hashing di una classe custom : suggerimenti?  (Letto 320 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 677
  • Punti reputazione: 0
    • Mostra profilo
hashing di una classe custom : suggerimenti?
« il: Settembre 16, 2022, 16:34 »
Sto realizzando delle procedure di studio/test miranti a derivare metodi per estrarre tabelle e righe "di codice" da un documento pdf.
Le operazioni di che trattasi si basano su di una matrice di caratteri "formattati" e corredati delle coordinate che ogni singolo carattere di testo presente in una pagina del pdf esaminato e, nello specifico della valutazione delle righe "di codice" ho deciso di definire come tali tutte le singole righe (aggregate per coordinate e rotazione) presentino le stesse caratteristiche di font ed occupazione uguali per tutti i caratteri.
Per la valutazione dei font ho implementato una classe di descrizione, che associo poi ad altri oggetti, che per le varie esigenze ho dotato dei metodi dunder "__eq__" ed "__hash__", che è così formata :
class DescrFont:
    def __init__(self, data):
        self.subset = ''
        self.font = ''
        self.size = 0
        self.points_size = 0
        self.style = ''
        self._parse(data)

    def _parse(self, data):
        self.size = data[1]
        self.points_size = self.size * 72 / 96
        tmp = data[0].split('+')
        if len(tmp) > 1:
            self.subset = tmp[0]
            tmp = tmp[1]
        else:
            tmp = tmp[0]
        tmp = tmp.split('-')
        self.font = tmp[0]
        if len(tmp) > 1:
            self.style = tmp[1]

    def __eq__(self, obj):
        if not isinstance(obj, DescrFont): return NotImplemented
        if obj.subset != self.subset: return False
        if obj.font != self.font: return False
        if obj.size != self.size: return False
        if obj.points_size != self.points_size: return False
        if obj.style != self.style: return False
        return True

    def __hash__(self):
        return hash(' '.join([self.subset,
                         self.font,
                         str(self.size),
                         '(' + str(round(self.points_size)) + ')',
                         self.style]))

    def __str__(self):
        return ' '.join([self.subset,
                         self.font,
                         str(self.size),
                         '(' + str(round(self.points_size)) + ')',
                         self.style])

Ho ritenuto, per lo hashing, che la stringa di descrizione del font sia una determinante valida e sufficiente, ed in effetti nei test sin ora effettuati, con utilizzi di comparazione diretta ovvero per generazione dati tramite comprehensions, la classe sembra funzionare bene però mi rendo conto di aver ben poco chiari tal genere di aspetti e mi viene la domanda:

Una implementazione del genere è ben fatta, oppure vi sono particolari che non ho presenti?

Ovviamente, mi rendo conto che una definizione di classe avulsa dal suo contesto di utilizzo può dar adito a perplessità, se si ritiene occorra nulla in contrario, ve lo ho risparmiato perché al momento sono circa 380 righe ed è ancora in evoluzione.
La domanda è fatta più che altro con l'aspettativa del suggerimento su accortezze da tenersi e/o indicazione di documenti validi in materia da studiarsi.

Grazie dell'attenzione, ciao :)

Offline GlennHK

  • python sapiens sapiens
  • ******
  • Post: 1.723
  • Punti reputazione: 1
    • Mostra profilo
    • La Tana di GlennHK
Re:hashing di una classe custom : suggerimenti?
« Risposta #1 il: Settembre 19, 2022, 09:09 »
Forse è più efficiente fare l'hash della tupla piuttosto che trasformare tutto in stringa, sicuramente hai meno allocazioni in memoria.

Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 677
  • Punti reputazione: 0
    • Mostra profilo
Re:hashing di una classe custom : suggerimenti?
« Risposta #2 il: Settembre 20, 2022, 09:11 »
Forse è più efficiente fare l'hash della tupla piuttosto che trasformare tutto in stringa, sicuramente hai meno allocazioni in memoria.

Della serie "com'è che non ci ho pensato?"   :(

Giusta osservazione e suggerimento @glennHK, Ti ringrazio ... per altro, tale uso di tupla potrebbe farsi anche per la verifica di uguaglianza, invece della serie di verifiche consecutive da me impostate, di tali varianti
    def __eq__(self, obj):
        if not isinstance(obj, DescrFont): return NotImplemented
        return (self.subset, self.font, self.size,
                self.points_size, self.style) == (obj.subset, obj.font, obj.size,
                                                  obj.points_size, obj.style)

    def __hash__(self):
        return hash((self.subset, self.font, self.size,
                     self.points_size, self.style))


non saprei quantificare se e quanto efficentano il codice ma certo lo snelliscono e funziona tutto come prima.

Grazie ancora. Ciao :)