3 votes

Est-il possible de surcharger les opérateurs pour les types de données natifs ?

Par exemple, si j'essaie de faire :

a_string + an_int

... où a_string est de type 'str' et an_int est de type 'int', ou :

an_int + a_string

Il y aurait un TypeError car il n'y a pas de conversion implicite des types. Je comprends que si j'utilisais mes propres sous-classes de int et string, je pourrais surcharger la fonction __add__() dans mes classes pour y parvenir.

Cependant, par curiosité, j'aimerais savoir : serait-il possible de surcharger l'opérateur + dans les définitions de classe de l'outil de gestion de l'environnement ? int y str de sorte que __add__(int,str) y __add__(str,int) les concaténer automatiquement en tant que chaînes de caractères ?

Si non, quelles sont les raisons pour lesquelles un programmeur ne devrait pas surcharger les opérateurs pour un type de données natif ?

2voto

Ami Tavory Points 24416

En général, sans revenir à l'API de niveau C, vous ne pouvez pas modifier les attributs des types construits (cf. aquí ). Vous pouvez cependant sous-classer les types construits et faire ce que vous voulez sur les nouveaux types. Pour la question que vous avez spécifiquement posée (rendre l'ajout basé sur les chaînes de caractères), vous modifiez les types suivants __add__ y __radd__ :

class Int(int):
    def __add__(self, other):
        return Int(int(str(self) + str(other)))

    def __radd__(self, other):
        return Int(str(other) + str(self))

>>> Int(5) + 3
53

>>> 3 + Int(5) + 87
3587

2voto

Synedraacus Points 482

Comme indiqué ci-dessus, vous ne pouvez pas le faire (sauf si vous êtes prêt à construire votre propre implémentation Python). C'est-à-dire que vous ne pouvez pas modifier la façon dont '1'+1 est traitée si elle est rencontrée dans le code. Mais vous pouvez jouer avec les fonctions intégrées fonctions comme vous le souhaitez :

>>> int = str
>>> type(1)
<class 'int'>
>>> type('1')
<class 'str'>
>>> int(1)
'1'
>>> type(int(1))
<class 'str'>

Ce n'est guère plus qu'un exemple éclairant de la génialité des fonctions de première classe, cependant. Toutes les modifications que vous apportez restent dans l'espace de nom dans lequel vous les faites. Considérez ceci :

>>> str=int
>>> str('1')
1
>>> str('asd')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'asd'
>>> input()
2
'2'
>>> 

Vous utilisez ce que vous mettez dans str dans ce cas int . Mais input() sait mieux et se rabat sur les builtins. Il y a peut-être un truc bizarre avec les closures qui permet de faire référence à votre implémentation, mais je ne le trouve pas. D'ailleurs, l'original str est en __builtins__.str si vous avez besoin de le récupérer.

Tirer le même tour sur les méthodes de builtin ne fonctionne pas :

>>> int.__add__ = str.__add__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'int'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X