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