Est-il possible de remplacer + = en Python?
Oui, remplacez le __iadd__
méthode. Exemple:
def __iadd__(self, other):
self.number += other.number
return self
En plus de ce qui est correctement donné dans les réponses ci-dessus, il convient de préciser explicitement que lorsque __iadd__
Est remplacé, l'opération x += y
Ne se termine PAS avec la fin de la méthode __iadd__
.
Au lieu de cela, il se termine par x = x.__iadd__(y)
. En d'autres termes, Python affecte la valeur de retour de votre implémentation __iadd__
À l'objet que vous "ajoutez", APRÈS la fin de l'implémentation.
Cela signifie qu'il est possible de muter le côté gauche de l'opération x += y
Afin que l'étape implicite finale échoue. Considérez ce qui peut se produire lorsque vous ajoutez quelque chose à l'intérieur d'une liste:
>>> x[1] += y # x has two items
Maintenant, si votre implémentation __iadd__
(Une méthode d'un objet à x[1]
) Supprime par erreur ou exprès le premier élément (x[0]
) Du début de la liste, Python exécutera alors votre méthode __iadd__
) Et essayera d'attribuer sa valeur de retour à x[1]
. Qui n'existera plus (il sera à x[0]
), Résultant en un ÌndexError
.
Ou, si votre __iadd__
Insère quelque chose au début de x
de l'exemple ci-dessus, votre objet sera à x[2]
, Pas à x[1]
, Et tout ce qui était antérieur à x[0]
sera désormais à x[1]
et se verra attribuer la valeur de retour de l'invocation __iadd__
.
À moins que l'on comprenne ce qui se passe, les bogues qui en résultent peuvent être un cauchemar à corriger.
En plus de surcharger __iadd__
(n'oubliez pas de retourner vous-même!), vous pouvez également recourir à __add__
, car x + = y fonctionnera comme x = x + y. (C'est l'un des pièges de l'opérateur + =.)
>>> class A(object):
... def __init__(self, x):
... self.x = x
... def __add__(self, other):
... return A(self.x + other.x)
>>> a = A(42)
>>> b = A(3)
>>> print a.x, b.x
42 3
>>> old_id = id(a)
>>> a += b
>>> print a.x
45
>>> print old_id == id(a)
False
Il a même voyage des experts :
class Resource(object):
class_counter = 0
def __init__(self):
self.id = self.class_counter
self.class_counter += 1
x = Resource()
y = Resource()
Quelles valeurs attendez-vous x.id
, y.id
, et Resource.class_counter
avoir?
http://docs.python.org/reference/datamodel.html#emulating-numeric-types
Par exemple, pour exécuter l'instruction x + = y, où x est une instance d'une classe qui a une méthode __iadd __ (), x .__ iadd __ (y) est appelée.