5

J'ai une classe dérivée int avec un opérateur de comparaison surchargé.Accès à la comparaison int originale à partir de la classe dérivée int avec opérateur de comparaison surchargé

Dans le corps des méthodes surchargées, j'ai besoin d'utiliser l'opérateur d'origine.

L'exemple de jouet:

>>> class Derived(int): 
...  def __eq__(self, other): 
...   return super(Derived, self).__eq__(other) 

fonctionne très bien avec Python 3.3+, mais échoue avec Python 2.7 à l'exception AttributeError: 'super' object has no attribute '__eq__'.

Je peux penser à plusieurs walkarrounds, que je trouve pas très propre:

return int(self) == other 

nécessite la création d'un nouvel objet int juste pour comparer, tandis que

try: 
    return super(Derived, self).__eq__(other) 
except AttributeError: 
    return super(Derived, self).__cmp__(other) == 0 

divise le flux de contrôle à base sur la version Python, que je trouve terriblement en désordre (donc inspecte la version Python explicitement).

Comment puis-je accéder à la comparaison de nombres entiers d'une manière élégante en travaillant avec Python 2.7 et 3.3+?

+1

Vous pouvez accéder à la 'int' méthode de comparaison via' super .__ eq__'. Cependant, en fonction de la version python, les méthodes de comparaison sont très différentes. Par conséquent python2 'super.eq' nécessite 1 argument (autre) alors que python3 requiert 2 (self et autre) – infotoni91

+0

Considérez-vous int (self) == int (other)' too much? – Phillip

+0

@Phillip crée un objet de plus que int (self) == other' – abukaj

Répondre

0

Je crois que vous devez définir le __eq__ dans le int avant de définir la classe. Par exemple:

int = 5 
def int.__eq__(self, other): 
    return self.real == other 
IntDerived = Derived(int) 

Cela devrait donner à la classe super un attribut __eq__.


ÉDITÉE


L'idée principale a fonctionné, mais il a été porté à mon attention que le code ne fonctionne pas. Donc: amélioration de code:

class Derived(int): 
    def __eq__(self, other): 
     return self.real == other 

Int = 5 
D = Derived(Int) 
D.__eq__(4) #Output: False 
D.__eq__(5) #Output: True 
+1

Ce n'est pas python. – Goyo

+0

@ GreenHawk1220 Je vais accepter la réponse si vous mettez la méthode '__eq __()' dans la définition de la classe 'Derived' (et la faites fonctionner en Python). L'idée d'accéder à l'attribut '.real' fonctionne, mais le code n'est pas Python. – abukaj

+0

Le code mis à jour a fonctionné pour moi. – GreenHawk1220

2

Python 2 et 3 sont significativement différents les uns des autres, donc je pense que vous devriez mordre la balle et vérifier les versions. C'est normal si vous essayez d'écrire du code qui fonctionne sur les deux (tôt ou tard dans mon expérience, vous trouverez quelque chose que vous devez corriger). Pour éviter tout impact sur les performances, vous pouvez faire quelque chose comme:

from six import PY2 

class Derived(int): 
    if PY2: 
     def __eq__(self, other): 
      return super(Derived, self).__cmp__(other) == 0 
    else: 
     def __eq__(self, other): 
      return super(Derived, self).__eq__(other) 

C'est ce que je ferais. Si je voulais vraiment sous-classe int ...

Si vous ne voulez vraiment pas, peut-être vous pouvez essayer:

class Derived(int): 
    def __eq__(self, other): 
     return (self^other) == 0 

Évidemment, si vous vous souciez de la performance que vous aurez à faire un peu de profilage avec le reste de votre code et savoir si l'un d'eux est significativement pire ...

+0

J'aime cette dernière approche, cependant cela ne fonctionne pas quand 'other' est un float – abukaj

0

à l'aide hasattr évite la création d'un nouvel objet int, attrapant une exception ou le contrôle explicitement pour la version Python.

Le code ci-dessous fonctionne sur Python 2.7 et 3.3+:

class Derived(int): 
    def __eq__(self, other): 
     return super(Derived, self).__cmp__(other) == 0 if hasattr(Derived, "__cmp__") else super(Derived, self).__eq__(other) 
1

Les deux versions mettent en œuvre une méthode __xor__, vous pouvez essayer ceci:

class Derived(int): 
    def __eq__(self, other): 
     return not super(Derived, self).__xor__(other) 
+0

J'aime la réponse. Pas très propre ni fonctionne avec la comparaison au flotteur, cependant. Aussi, je pense qu'il n'y a pas de nécessité de créer un objet 'super',' self' suffit. 'self^other' peut être encore plus simple. – abukaj