Reflection operations
What is the reflection operator, in fact, is reversed two objects, the following first look at the implementation of a common runner:
classFoo (object):def __init__(self, x): self.x=xdef __add__(self, Other):return 'foo:%s +%s'%(self.x, other.x)classBoo (object):def __init__(self, x): self.x=xdef __add__(self, Other):return 'boo:%s +%s'%(self.x, other.x) a= Foo (123) b= Boo (321)PrintA +bPrintB + A
In the ordinary addition operation, the call is the __add__ method on the left of the + number, which is called as self. So the left side is self and the right side is other, so the result is as above.
And the reflection is actually the exchange of the two, see the example below:
classFoo (object):def __init__(self, x): self.x=xdef __radd__(self, Other):return 'foo:%s +%s'%(self.x, other.x)classBoo (object):def __init__(self, x): self.x=xdef __radd__(self, Other):return 'boo:%s +%s'%(self.x, other.x) a= Foo (123) b= Boo (321)PrintA +bPrintB + A
First, the different place is the __radd__ method that is called here and the right after the +. Then it was the self of the left and now the right one for self.
To sum up: the normal operation calls the method to the left of the operator, and the reflection operator calls the method on the right, whose method is called, and who is self.
Here are a few things to keep in mind:
1. Instances of the same class are not supported for reflection operations:
class Foo (object): def __init__ (self, x): = x def__radd__(self, Other): return' foo:%s +%s ' %= foo (123= foo (321)print A + bprint b + A
2. When a class implements the __add__, it will mask the __radd__ method, which means that the __add__ has higher precedence:
classFoo (object):def __init__(self, x): self.x=xdef __radd__(self, Other):return 'foo:%s +%s'%(self.x, other.x)classBoo (object):def __init__(self, x): self.x=xdef __add__(self, Other):return 'Boo add:%s +%s'%(self.x, other.x)def __radd__(self, Other):return 'Boo radd:%s +%s'%(self.x, other.x) a= Foo (123) b= Boo (321)PrintA +bPrintB + A
The logic is as follows:
First A + B,python see there is no __add__ method in a (ignoring __radd__), go to B to find __radd__ (not __add__), because on the right side, it means to use the reflection operation. So I finally got the result .
Then B + A,python saw the __add__ method in B and called it directly, no matter what the inside of a is.
The basic reflection operation is such a thing, here are some summary:
__radd__ (self, other)
Reflection addition
__rsub__ (self, other)
of reflection subtraction
__rmul__ (self, other)
Reflection Division
__rfloordiv__ (self, other)
Reflective flooring Except, using the//operator
__rdiv__ (self, other)
Reflection Division, using the/operator.
__rtruediv__ (self, other)
Reflection is true. Note It only works when the From __future__ import division.
__rmod__ (self, other)
The reflection modulo operation, using the% operator.
__rdivmod__ (self, other)
Long division, using the Divmod () built-in function, is called when Divmod (other,self).
__rpow__
The reflection exponentiation, using the * * operator's
__rlshift__ (self, other)
The reflection moves left, using the << operator.
__rrshift__ (self, other)
The reflection moves right, using the >> operator.
__rand__ (self, other)
Reflection bit with, using the & operator.
__ror__ (self, other)
Reflection bit or, using the | operator.
__rxor__ (self, other)
Reflection Xor, using the ^ operator.
Increment operation
The so-called increment operation is actually the form of x + = 1, here are a few examples:
class Foo (object): def __init__ (self, x): = x def__iadd__(self, Other): return' Foo Iadd:%s +%s ' %= Foo (123+ = 1print A
however , if the implementation of the two objects is __iadd__, the situation will be significantly different:
classFoo (object):def __init__(self, x): self.x=xdef __iadd__(self, Other):return 'Foo Iadd:%s +%s'%(self.x, other.x)classBoo (object):def __init__(self, x): self.x=xdef __iadd__(self, Other):return 'Boo Iadd:%s +%s'%(self.x, other.x) a= Foo (123) b= Boo (321) A+=bPrintA
It seems normal, however the code is as follows:
A = Foo (123= Boo (321+ = bprint+ aprint b
Error shows: STR does not have an X attribute, but according to the code, two objects have an X attribute.
In B + + A This line is wrong, that is, self is b,other a. It was later tested and found to be:
return 'Boo iadd:%s +%s' % (self.x, other.x)
Switch
return 'Boo iadd:%s +%s' % (self.x, other)
The code will not error, but the output is as follows:
Strangely, other becomes the return value of __iadd__ in a, that is, when a calls the __iadd__ method, when it is used in other increment operations, other does not represent the A object itself, but the return value of its __iadd__.
When we return to its essence: x + = 1 ==> x = x + 1 It can be seen that x is actually re-assigned and re-assigned as the return value of __iadd__. In our code example, the return value of this method is a string. At the beginning, X is an instance of our class. However, after the increment operation, X becomes the return value of the Magic method, that is, the string, so the above error occurs.
So we should pay attention to the change of the identity of X when using, otherwise there will be many unexpected troubles.
A summary of incremental methods:
-
__iadd__ (self, other)
-
Addition assignment
-
__isub__ (self, other)
-
Subtraction assignment.
-
__imul__ (self, other)
-
Multiplication assignment
-
__ifloordiv__ (self, other)
- The
divides the assignment, except for the floor, which is equivalent to the//= operator.
-
__idiv__ (self, other)
The
-
Division assignment, which is equivalent to the/= operator.
-
__itruediv__ (self, other)
-
True except assignment, note that only you whenfrom __future__ import Divisionis is valid.
-
__imod_ (self, other)
The
-
Modulo assignment, equivalent to the%= operator.
-
__ipow__
The
-
is assigned a value equal to the **= operator.
-
__ilshift__ (self, other)
The
-
Shifts the assignment to the left, which is equivalent to the <<= operator.
-
__irshift__ (self, other)
The
-
Shifts the assignment to the left, equivalent to the >>= operator.
-
__iand__ (self, other)
-
and assignment, equivalent to the &= operator.
-
__ior__ (self, other)
-
or assignment, equivalent to the |= operator.
-
__ixor__ (self, other)
The
-
Xor operator, which is equivalent to the ^= operator.
You are welcome to exchange.
Reference: Poke here
Python Magic Methods-reflection and increment operations