Reprint: Python's Magic Method guide: Make an operator work within a custom class

Source: Internet
Author: User
Tags arithmetic operators bitwise floor division

One of the advantages of using the Python magic method is that it provides an easy way to make objects behave like built-in types. This means that you can avoid performing basic operations with ugly, anti-intuitive, and nonstandard methods. In some languages, this is usually done:

If Instance.equals (other_instance):    # do something

You should also do this in Python, but at the same time it will increase the user's doubts and unnecessary verbosity. Different libraries may have different names for the same operations, which allows users to do more than usual. Depending on the power of the magical method, you can define a method (such as __eq__), and then take our true intentions instead:

If instance = = other_instance:    # do something

Now what you see is part of the magical power of the method. The vast majority allow us to define the meaning of the operators themselves, when used on our own defined classes as if they were built-in types.

The Magic Method-Comparison

Python has a whole set of magical methods designed to use operators to achieve intuitive comparisons between objects, rather than awkward method invocations. They also provide a set of default behaviors that override Python object comparisons (by reference). The following is a list of these methods and how to do it:

__cmp__ (self, other)

__cmp__ is one of the most fundamental of the magical methods. It actually implements all the comparison operator behaviors (<,==,!=, etc.), but it may not work the way you want (for example, whether one instance equals another depends on the criteria for comparison, and whether one instance is greater than the other). If self < Another, that __cmp__ should return a negative integer, or 0 if self = = other, or a positive integer if self > another. It's usually the best definition, without having to define them all at once, but when you need to do all the comparisons with similar criteria, __cmp__ is a great way to save you from repetition and improve clarity.

__eq__ (self, other)

Defines the behavior of the equality operator, = =.

__ne__ (self, other)

Defines the behavior of the inequality operator,! =.

__lt__ (self, other)

The behavior that is less than operator,< is defined.

__gt__ (self, other)

The behavior that is greater than the operator,> is defined.

__le__ (self, other)

Defines the behavior of <=, which is less than or equal to the operator.

__ge__ (self, other)

Defines the behavior of the >=, which is greater than or equal to the operator.

For example, imagine a class definition for a word. We might want to be able to compare words internally to the default comparison of strings, that is, dictionary order (by letter), and also to be able to base on some other criteria, like length or number of syllables. In this example, we sort by the word length, the following gives the implementation:

Class Word (str):    "' word classes, comparison definitions are based on the word length of '    def __new__ (CLS, Word):        # Note that we used __new__ because STR is an immutable type,        # So we have to initialize it earlier (at the time of creation)        if "in Word:            print" word contains a space, truncated to the first part "            Word = Word[:word.index (')] # before the first space appears It's all character. Now        return str.__new__ (CLS, word)    def __gt__ (self, Other):        return Len (self) > len (Other)    def _ _lt__ (self, Other):        return len < Len (all)    def __ge__ (self, Other):        return len (self) >= len (Other)    def __le__ (self, Other):        return len (self) <= len (Other)

Now we can create 2 words (through word (' foo ') and Word (' bar ') and compare them based on their length. Note that we do not define __eq__ and __ne__. This is because this can lead to some weird behavior (especially when comparing word (' foo ') = = Word (' bar ') will get True results). Equality comparisons based on word lengths can be confusing, so we follow the implementation of the equality comparison of STR itself.

Now might be a good time to remind you that you don't have to reload each of the more relevant magical methods to get a variety of comparisons. The standard library has been friendly for us to provide a decorative (decorator) class in template Functools, which defines all the comparison methods. You can overload only __eq__ and one other method (such as __gt__,__lt__, etc.). This feature is only in Python2.7 (after?) Apply, but you should try it if you have a chance, it will save you a lot of time and trouble. You can use it by adding @total_ordering in your own overloaded method.

Magic Method-Digital

Just as you can create your own class instances by overloading the comparison operators, you can also reload the numeric operators. Fasten your seat belts, friends, and many more. In the need of this organization, I will divide the magic of numbers into 5 pieces: unary operators, general arithmetic operators, reflection arithmetic operators, increment assignments, type conversions.

Unary operator

Unary operations and functions have only one operand, such as negative numbers, absolute values, etc.

__pos__ (self)

The behavior of implementing unary positive numbers (for example: +some_object)

__neg__ (self)

Implement negative behavior (for example:-some_object)

__abs__ (self)

Implementing the behavior of the built-in ABS () function

__invert__ (self)

Implements the inverse behavior with the ~ operator. You can refer to wiki:bitwise operations to explain what this operator will do.

General arithmetic operators

Now we cover the basic two-dollar operator: +,-,* and so on. Most of them are self-explanatory.

__add__ (self, other)

implementing addition

__sub__ (self, other)

Implementing subtraction

__mul__ (self, other)

Implement multiplication

__floordiv__ (self, other)

Implement floor division, using//Operator

__div__ (self, other)

Implementing traditional division, using/operator

__truediv__ (self, other)

Achieve true division. Note that it only works if you are from __future__ import division

__mod__ (self, other)

Implementing modulo, using the% operator

__divmod__ (self, other)

Implementing the behavior of the built-in function divmod ()

__pow__ (self, other)

To achieve the exponentiation, use the * * operator

__lshift__ (self, other)

Implement left bitwise displacement, using the << operator

__rshift__ (self, other)

Implement right-click displacement, using the >> operator

__and__ (self, other)

Implement bitwise-AND, use & operators

__or__ (self, other)

Implementing a bitwise OR, using | Operator

__xor__ (self, other)

Implementing bitwise XOR, using the ^ operator

Reflection arithmetic operator

Do you know how I would explain the reflection arithmetic operator? Some of you might think it's big and scary, and it's a foreign concept. But it's actually quite simple, here's an example:

Some_object + Other

This is the "regular" addition. And reflection is actually equivalent to the same thing, except that the operand changes the next position:

Other + Some_object

Therefore, all these magical methods will do the same thing equivalent to the regular arithmetic operators, in addition to changing the position of the operands, such as the first operand and itself as the second. In addition, there is no other way to operate. In most cases, the result of the reflection arithmetic operation is equivalent to a regular arithmetic operation, so you can call __add__ as soon as you have finished overloading the __radd__. Simply Jolly:

__radd__ (self, other)

Implementing Reflection Addition

__rsub__ (self, other)

Implementing Reflection Subtraction

__rmul__ (self, other)

Implementing Reflection multiplication

__rfloordiv__ (self, other)

Implement reflective Flooring In addition to//operator

__rdiv__ (self, other)

Implementing traditional division, using/operator

__rturediv__ (self, other)

Achieve true division, note that it only works if you are from __future__ import division

__rmod__ (self, other)

Realization of reflection modulus, with% operator

__rdivmod__ (self, other)

Implements the long-removed behavior of the built-in function Divmod (), called when Divmod (other,self) is called

__rpow__ (self, other)

Implement Reflection exponentiation with * * operator

__rlshift__ (self, other)

Implementing the Left bitwise displacement of reflection, using the << operator

__rrshift__ (self, other)

Implement right-click displacement of reflection, using >> operator

__rand__ (self, other)

Implement the bitwise AND of reflections, using the & operator

__ror__ (self, other)

Implementing a bitwise OR of reflection, using | Operator

__rxor__ (self, other)

To implement a bitwise XOR of a reflection, use the ^ operator

Increment assignment

Python also has a variety of magical methods that allow users to customize incremental assignment behavior. You may already be familiar with incremental assignments, which combine the "regular" operators with the assignment values. If you still don't understand what I'm saying, here's an example:

x = 5x + = 1 # equivalent x = x + 1

None of these methods have a return value, because the assignment does not have any return value in Python. Instead they just change the state of the class. The list is as follows:

__iadd__ (self, other)

implementing Addition and assignment

__isub__ (self, other)

Implementing Subtraction and Assignment

__imul__ (self, other)

Implement multiplication and assignment

__ifloordiv__ (self, other)

Implementation of floor addition and assignment, with//= operator

__idiv__ (self, other)

Implement traditional division and assignment with the/= operator

__iturediv__ (self, other)

Achieve true division and assignment, note that only valid if you are from __future__ import division

__imod__ (self, other)

Implement modulo and assignment, using the%= operator

__ipow__ (self, other)

Implement exponentiation and assignment with the **= operator

__ilshift__ (self, other)

Implement left bitwise displacement and assignment using the <<= operator

__irshift__ (self, other)

Implement right-bitwise displacements and assignments using the >>= operator

__iand__ (self, other)

Implement bitwise AND and assignment using the &= operator

__ior__ (self, other)

Implementing bitwise OR and assignment using the |= operator

__ixor__ (self, other)

Implementing bitwise XOR and Assignment using the ^= operator

The Magic way of type conversion

Python also has a set of magic methods that are designed to implement the behavior of built-in type conversion functions, such as float ()

__int__ (self)

Implementing type conversions to int

__long__ (self)

Implementing a type conversion to a long

__float__ (self)

Implementation of type conversion to float

__complex__ (self)

Implementing a type conversion to a complex number

__oct__ (self)

Implementing a type conversion of 8 binary

__hex__ (self)

Implementing a type conversion of 16 binary

__index__ (self)

Implements a type conversion when an object is sliced into int. If you customize a numeric type, consider that it may be sliced, so you should reload __index__

__trunc__ (self)

Called when Math.trunc (self) is invoked. __TRUNC__ should return a truncation of an integral type (usually a long)

__coerce__ (self, other)

This method is used to implement mixed-mode arithmetic. If the type conversion is not possible that __coerce__ should return None. Otherwise, it should return a pair containing self and other (2 tuples), and adjust to having the same type

Reprint: Python's Magic Method guide: Make an operator work within a custom class

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.