:PROPERTIES: :ID: d1877b3b-3fe5-43d5-9be2-afb5ffe6b918 :mtime: 20220522095337 :ctime: 20220520230639 :END: #+title: La méthode __hash__ * Synthaxe #+BEGIN_SRC python class.__hash__(self) #+END_SRC La méthode ~class.__hash__~ : * Est appelée par la /built-in method/ ~hash()~ et pour les opérations sur les membres des /hashed collection/ telles que /set/, /frozenset/ et /dict/, * Doit retourner un /int/, * Deux objet *égaux* doivent retourner la même valeur, * Si une classe *ne définit pas* de méthode ~__eq__~, elle ne doit pas définir de méthode ~__hash__~, * Si une classe *définit* une méthode ~__eq__~, mais pas de méthode ~__hash__~, ses instances : * Une méthode ~__hash__~ par défaut et retournant ~None~ est créée automatiquement, * Ne pourront pas être utilisées par les /hashable collections/, * Si une classe *définit* un objet /mutable/ et *définit* une méthode ~__eq__~, elle *ne doit pas* définir de méthode ~__hash__~, l'implémentation des /hashables collections/ nécessitant que la valeur des clés soit /immutable/, * Par défaut, les classes définit par l'utilisateur possèdent les méthodes ~__eq__~ et ~__hash__~ (~id(obj) >> 4~): tous les objets sont comparés comme non-égaux (sauf chaque objet avec lui-même). Si ~a == b~, alors ~hash(a) == hash(b)~. Si ~hash(a) == hash(b)~, alors ~a~ pourait être égal à ~b~. Si ~hash(a) != hash(b)~, alors ~a != b~. * Exemples #+BEGIN_SRC python :results output from __future__ import annotations print(f'{hash(10)=}') print(f'{hash("abc")=}') class Dummy: def __init__(self, first: str, second: str) -> None: self.first = first self.second = second class HashableDummy: def __init__(self, first: str, second: str) -> None: self.first = first self.second = second def __eq__(self, other: HashableDummy) -> bool: return (other is not None and isinstance(other, HashableDummy) and self.first == other.first and self.second == other.second) def __hash__(self) -> int: return hash((self.first, self.second)) dummy1, dummy2 = (Dummy("a", "b") for _ in range(2)) print(f'{hash(dummy1)=}') print(f'{hash(dummy2)=}') print(f'{dummy1 == dummy2=}') hashable_dummy1, hashable_dummy2 = (HashableDummy("a", "b") for _ in range(2)) print(f'{hash(hashable_dummy1)=}') print(f'{hash(hashable_dummy2)=}') print(f'{repr(hashable_dummy1)=}') print(f'{repr(hashable_dummy2)=}') print(f'{hashable_dummy1 == hashable_dummy2=}') #+END_SRC #+RESULTS: : hash(10)=10 : hash("abc")=-9106817633146148147 : hash(dummy1)=8779192445928 : hash(dummy2)=8779192413751 : dummy1 == dummy2=False : hash(hashable_dummy1)=2529530665278513875 : hash(hashable_dummy2)=2529530665278513875 : repr(hashable_dummy1)='<__main__.HashableDummy object at 0x7fc10a69f4c0>' : repr(hashable_dummy2)='<__main__.HashableDummy object at 0x7fc10a51a1c0>' : hashable_dummy1 == hashable_dummy2=True * Références * [[https://docs.python.org/3/reference/datamodel.html#object.__hash__][object.__hash__ - Docs Python]] * [[https://zestedesavoir.com/tutoriels/954/notions-de-python-avancees/1-starters/3-mutables-hashables/#3-3-hashables][Hashables - Zeste de savoir]] * [[https://eng.lyft.com/hashing-and-equality-in-python-2ea8c738fb9d][Hashing and equality in Python - Roy Williams]]