# Right-Side and In-Place Uses: __radd__ and __iadd__
# Why we need Right-Side Addition
>>> class Adder:
... def __init__(self, value=0):
... self.data = value
... def __add__(self, other):
... return self.data + other
...
>>> x = Adder(5)
>>> x + 2
7
>>> 2 + x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'Adder'
>>>
# Add __radd__
>>> class Commuter:
... def __init__(self, val=0):
... self.data = val
... def __add__(self, other):
... print('add', self.data, other)
... return self.data + other
... def __radd__(self, other):
... print('radd', self.data, other)
... return other + self.data
...
>>> x = Commuter(99)
>>> x + 1
add 99 1
100
>>> 1 + x
radd 99 1
100
>>> y = Commuter(100)
>>> x + y
add 99 <__main__.Commuter object at 0x0075B090>
radd 100 99
199
>>>
# Reusing __add__ in __radd__
class Commuter1:
def __init__(self, val=0):
self.data = val
def __add__(self, other):
return self.data + other
def __radd__(self, other):
return self.__add__(other) # Call __add__ explicitly
class Commuter2:
def __init__(self, val=0):
self.data = val
def __add__(self, other):
return self.data + other
def __radd__(self, other):
return self + other # Swap order and re-add
class Commuter3:
def __init__(self, val=0):
self.data = val
def __add__(self, other):
return self.data + other
__radd__ = __add__ # Alias: cut out the middleman
# Propagating class type
>>> class Commuter:
... def __init__(self, val=0):
... self.data = val
... def __add__(self, other):
... return Commuter(self.data + other) # What if return self.data + other directly ??
... def __radd__(self, other):
... return Commuter(other + self.data)
... def __str__(self):
... return '<Commuter: %s>' % self.data
...
>>> x = Commuter(2)
>>> y = Commuter(3)
>>> print(x)
<Commuter: 2>
>>> print(x + y)
<Commuter: <Commuter: 5>>
>>> z = x + y
>>> print(z)
<Commuter: <Commuter: 5>>
>>> print(z + x + y)
<Commuter: <Commuter: <Commuter: <Commuter: 10>>>>
>>>
# Add type-test to avoid object nested
>>> class Commuter:
... def __init__(self, val=0):
... self.data = val
... def __add__(self, other):
... if isinstance(other, Commuter):
... other = other.val
... return Commuter(self.data + other)
... def __radd__(self, other):
... return Commuter(other + self.data)
... def __str__(self):
... return '<Commuter: %s>' % self.data
...
>>> x = Commuter(2)
>>> y = Commuter(3)
>>> print(x)
<Commuter: 2>
>>> print(x + y)
<Commuter: 5>
>>> z = x + y
>>> print(z)
<Commuter: 5>
>>> print(z + x + y)
<Commuter: 10>
>>>
# In-Place Addition +=
# To also implement += in-place augmented addition, code either an __iadd__ or an __add__
# The __iadd__ runs often more efficient for in-place changes,
# though __add__ also support in-place changes
>>> class Number:
... def __init__(self, val):
... self.data = val
... def __iadd__(self, other):
... self.data += other
... return self
...
>>> x = Number(5)
>>> x += 1
>>> x += 1
>>> x.data
7
>>>
Using __iadd__ & __radd__
最新推荐文章于 2021-03-01 13:54:36 发布