Comment fournir de l'initialisation supplémentaires pour une sous-classe de namedtuple?

Supposons que j'ai un namedtuple comme ceci:

EdgeBase = namedtuple("EdgeBase", "left, right")

Je veux mettre en œuvre une coutume fonction de hachage pour cela, j'ai donc créer le sous-classe:

class Edge(EdgeBase):
    def __hash__(self):
        return hash(self.left) * hash(self.right)

Puisque l'objet est immuable, je veux que le hachage de la valeur calculée qu'une seule fois, donc ce que je fais:

class Edge(EdgeBase):
    def __init__(self, left, right):
        self._hash = hash(self.left) * hash(self.right)

    def __hash__(self):
        return self._hash

Cela semble fonctionner, mais je suis vraiment pas sûr de sur-classement et l'initialisation en Python, en particulier avec des n-uplets. Existe-il des inconvénients de cette solution? Est-il recommandé de comment faire cela? Est-il bien? Merci à l'avance.

  • Des Tests ont montré que ce n'est pas la peine de cache de la valeur de hachage, voir problème n ° 9685
  • Note: La manière canonique de combiner les hachages de calculer le hash d'un tuple des valeurs combinées; tuple utilise un plus testé, de façon fiable combinant les hachages de plus naïve des solutions (nettement mieux que la simple multiplication des hachages). Donc, si vous venez de ne pas surcharger de hachage, tuple's de hachage par défaut, ce serait déjà correcte et efficace (plus efficace que tout ce que vous allez écrire, car il n'exécute aucune Python niveau de byte code). Même si ce n'était pas un namedtuple, la bonne solution serait hash((self.left, self.right)).
  • bon point. C'était il y a si longtemps, mais si je me souviens bien, la fonction de hachage a été choisi comme ça parce que la classe représentée non orienté bords, de sorte que dans ce cas, il le tuple approche ne fonctionne pas.
  • Dans ce cas, le hash d'un frozenset des valeurs de travail. Pas aussi bien à la production unique de hachages comme tuple's de hachage (frozenset juste mélange jusqu'les bits de façon prévisible, alors xors ensemble), mais bien sûr, dans ce cas, c'est le but.