Python Magic Methods-reflection and increment operations

Source: Internet
Author: User

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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.