预计阅读本页时间:-
Right-Side and In-Place Addition: __radd__ and __iadd__
Technically, the __add__ method that appeared in the prior example does not support the use of instance objects on the right side of the + operator. To implement such expressions, and hence support commutative-style operators, code the __radd__ method as well. Python calls __radd__ only when the object on the right side of the + is your class instance, but the object on the left is not an instance of your class. The __add__ method for the object on the left is called instead in all other cases:
>>> class Commuter:
... def __init__(self, val):
... self.val = val
... def __add__(self, other):
... print('add', self.val, other)
... return self.val + other
... def __radd__(self, other):
... print('radd', self.val, other)
... return other + self.val
...
>>> x = Commuter(88)
>>> y = Commuter(99)
>>> x + 1 # __add__: instance + noninstance
add 88 1
89
>>> 1 + y # __radd__: noninstance + instance
radd 99 1
100
>>> x + y # __add__: instance + instance, triggers __radd__
add 88 <__main__.Commuter object at 0x02630910>
radd 99 88
187
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
Notice how the order is reversed in __radd__: self is really on the right of the +, and other is on the left. Also note that x and y are instances of the same class here; when instances of different classes appear mixed in an expression, Python prefers the class of the one on the left. When we add the two instances together, Python runs __add__, which in turn triggers __radd__ by simplifying the left operand.
In more realistic classes where the class type may need to be propagated in results, things can become trickier: type testing may be required to tell whether it’s safe to convert and thus avoid nesting. For instance, without the isinstance test in the following, we could wind up with a Commuter whose val is another Commuter when two instances are added and __add__ triggers __radd__:
>>> class Commuter: # Propagate class type in results
... def __init__(self, val):
... self.val = val
... def __add__(self, other):
... if isinstance(other, Commuter): other = other.val
... return Commuter(self.val + other)
... def __radd__(self, other):
... return Commuter(other + self.val)
... def __str__(self):
... return '<Commuter: %s>' % self.val
...
>>> x = Commuter(88)
>>> y = Commuter(99)
>>> print(x + 10) # Result is another Commuter instance
<Commuter: 98>
>>> print(10 + y)
<Commuter: 109>
>>> z = x + y # Not nested: doesn't recur to __radd__
>>> print(z)
<Commuter: 187>
>>> print(z + 10)
<Commuter: 197>
>>> print(z + z)
<Commuter: 374>