Forum Python

Fil d’Ariane du forum – Vous êtes ici :ForumLangage Python: Langage PythonHash cohérent()
Please or S’enregistrer to create posts and topics.

Hash cohérent()

Je suis en train de coder des classes et je souhaite définir la méthode __hash__ afin de l'utiliser pour créer des identifiants cohérents pour les objets de ces classes, de sorte que si leur structure de données (certaines autres variables d'instance) ne change pas, l'identifiant reste le même. Cependant, en utilisant hash(), j'ai compris par essais et erreurs qu'il change à chaque exécution de Python. Existe-t-il une solution pythonique pour gérer ce cas d'utilisation ?

Par exemple, j'essaie ceci, mais je suis encore en train de déboguer des erreurs d'exécution dues à la complexité de la gestion des int, str ou bytes avec les différentes fonctions.

from typing import List, Optional, Union
from pydantic import BaseModel, Field, computed_field
import hashlib
import base64

class File(BaseModel):
    filename: str
    content: Optional[Union[str, bytes]] = None
    encoding: Optional[str] = None
    id_attachment: Optional[str] = Field(default=None, init=False)

    @computed_field
    @property
    def extension(self) -> str:
        return os_split_extension(self.filename)[-1].lower()
    
    def __hash__(self):
        if isinstance(self.content, str):
            # Decode content if it's base64 encoded
            content_bytes = base64.b64decode(self.content)
        else:
            content_bytes = self.content or b''

        # Concatenate filename and content bytes
        hash_input = self.filename.encode() + content_bytes
        return int.from_bytes(hashlib.sha256(hash_input).digest(), byteorder='big')

class EmailAddress(BaseModel):
    nickname: Optional[str] = None
    address: str

    def __str__(self):
        return self.address
    
    def __hash__(self):
        # Concatenate nickname and andress
        hash_input = (self.nickname or "").encode() + self.address.encode()
        return int.from_bytes(hashlib.sha256(hash_input).digest(), byteorder='big')

 

Je n'aime pas vraiment mon code car il ne me semble pas propre et semble sujet aux erreurs. Comment puis-je être plus cohérent ici ? Puis-je exploiter des bibliothèques ou des méthodes pythoniennes pour mieux gérer cela ?

Je souhaite également construire d'autres modèles à partir de ceux-ci, par exemple. Dois-je enregistrer le hash d'une manière ou d'une autre afin de construire le hash du modèle composite en récupérant les hash des modèles de variables d'instance ?

Je recommanderais la bibliothèque attrs. Si vous acceptez de geler la classe, vous pouvez avoir un hachage qui devrait être invariant entre les sessions. Si vous ne souhaitez pas geler la classe, le hachage le plus raisonnable dépend du pointeur vers l'objet, qui ne sera pas indépendant entre les sessions. Un hack auquel je peux penser est de créer une copie gelée de votre objet, puis de calculer le hachage de cet objet. Mais cela semble être une mauvaise idée d'implémenter un tel hack dans __hash__.

Cela ne fait que demander des bugs et des erreurs.