Operator overloading simply means intercepting built-in operations in a class method, which means that when an instance of the class appears in the built-in operation, Python automatically calls our method, and the return value of our method becomes the result of the corresponding operation.
Key points of knowledge about overloading:
- Operator overloading allows a class to intercept regular Python operations
- Class can overload all Python expression operators
- Class can also overload the built-in operations such as printing, function invocation, attribute point number arithmetic
- Overloading makes a class instance behave like a built-in type
- Overloading is achieved by providing a class method that provides a special name.
In other words, when a method of a particular name is provided in a class, Python automatically calls them when instances of the class appear in their related expressions.
Of course, some operators are not overloaded: assignment operators , logical operators . In C + +, assignment operators and logical operators can be overloaded.
Operator overloading
Next we see an example of a real number, and we all know that the real number contains both real and imaginary parts, and this example mainly implements the addition of two real numbers. The code is as follows:
class Complex: def __init__(self, real, imag): self.real = real self.imag = imag def add(self, other): return Complex(self.real+other.real, self.imag+other.imag) def sub(self, other): return Complex(self.real-other.read, self.imag-other.imag)c1 = Complex(1, 1)c2 = Complex(2, 3)c3 = c1.add(c2)c3.real3c3.imag4c1 + c2 # 此处出问题了,试图让两个对象相加---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-7-61818d23e61f> in <module>()----> 1 c1 + c2TypeError: unsupported operand type(s) for +: ‘Complex‘ and ‘Complex‘
Make a slight modification to the above program to increase the overloads of the subtraction operator:
class Complex: def __init__(self, real, imag): self.real = read self.imag = imag def __add__(self, other): return Complex(self.real + other.real, self.imag + other.imag) def __sub__(self, other): return Complex(self.real - other.read, self.imag - other.imag)c1 = Complex(1, 1)c2 = Complex(2, 3)c4 = c1 + c2c4.realc4.imag
Method names are preceded by a double-underline method, called a proprietary or magic method. The method with double underlines has a special meaning.
Let's also look at how operator overloading is implemented in C + +, with the following code:
#include <iostream>using namespace std;class Complex {private: int real; int imag;public: Complex(int real=0, int imag=0) { this->real = real; this->imag = imag; } int get_real() { return this->real; } int get_imag() { return this->imag; } Complex operator+(const Complex& c) { Complex complex; complex.real = this->real + c.real; complex.imag = this->imag + c.imag; return complex; }};int main(int argc, char *argv[]){ Complex c1(1, 1); Complex c2(2, 3); Complex c3; c3 = c1 + c2; cout << "c3.real = " << c3.get_real() << endl; cout << "c3.imag = " << c3.get_imag() << endl; return 0;}
Compile and run:
$ g++ complex.cpp -o complex$ ./complex c3.real = 3c3.imag = 4
By comparing the two examples above, we can easily find that implementing operator overloading in Python requires very little code (only for this Python example) to complete, and C++
more code (in this case, more than 50 lines) in the language of the use or other compiled type. By comparing the two code styles above, do you find that object-oriented programming in programming languages looks alike? If the answer is yes, then we do understand or grasp the problem of object-oriented programming, no matter what programming language it is.
We have implemented the addition and subtraction of two objects, which means that the addition and subtraction operators are overloaded in the class. Let's look at one more example, we implement the multiplication operator overloading. The code is as follows:
class Calc: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return Calc(self.x + other.x, self.y + other.y) def __mul__(self, other): return Calc(self.x * other.x, self.y * other.y)>>> c1 = Calc(10, 2)>>> c2 = Calc(8, 4)>>> c3 = c1 + c2>>> c3.x18>>> c3.y6>>> c4 = c1 * c2>>> c4.x80>>> c4.y8
OK, so much for example. How do I see which operators of an object can be overloaded? Under the interactive interpreter interface, view by help
command. such as viewing int
the operator overloads that an object can support:
Help on class int in module Builtins:class int (object) | Int (x=0), integer | int (x, base=10), Integer | | Convert a number or string to an integer, or return 0 if no arguments | is given. If x is a number, return x.__int__ (). For floating point | Numbers, this truncates towards zero. | | If x is not a number or if base was given, then x must a string, | Bytes, or ByteArray instance representing an integer literal in the | Given base. The literal can preceded by ' + ' or '-' and is surrounded | by whitespace. The base defaults to 10. Valid bases is 0 and 2-36. | Base 0 means to interpret the base from the string as an integer literal. | >>> int (' 0b100 ', base=0) | 4 | | Methods defined here: | | __abs__ (self,/) # Absolute | ABS (self) | | __add__ (self, value,/) # Addition | Return Self+value. | | __and__ (self, value,/) # Logic and | Return Self&value. | | __bool__ (self,/) # BOOL | Self! = 0 | | __ceil__ (...) | Ceiling of an Integral returns itself. | | __divMod__ (self, value,/) | Return Divmod (self, value). | | __eq__ (self, value,/) # Equal | Return Self==value. | | __float__ (self,/) | Float (self) | | __floor__ (...) | Flooring an Integral returns itself. | | __floordiv__ (self, value,/) | Return Self//value. | __format__ (...) | Default Object Formatter | | __GE__ (self, value,/) # Greater than equals | Return Self>=value. | | __getattribute__ (self, Name,/) | Return getattr (self, name). | | __getnewargs__ (...) | | __gt__ (self, value,/) # greater than | Return Self>value. | | __hash__ (self,/) | Return hash (self). | | __index__ (self,/) | Return self-converted to an integer, if-is suitable-as-a index into a list. | | __int__ (self,/) | int (self) # omit a lot
Built-in function overloading
Built-in functions can also be overloaded, and if you want to change the object's default behavior, you need to overload its built-in functions. To give a simple example:
class Person: def __init__(this, name, age): this.name = name this.age = agep = Person(‘lavenliu‘, 28)print(p) # 打印对象时,默认打印的是其在内存中的地址<__main__.Person object at 0x1045b7a58>
If we want to print the object and print its name and age, we'll reload the __str__
built-in method. The above code is modified as follows:
class Person: def __init__(this, name, age): this.name = name this.age = age def __str__(this): return ‘{}: {}, {}‘.format(__class__.__name__, this.name, this.age)p = Person(‘Taoqi‘, 25)print(p)Person: Taoqi, 25
Above, we overload the built-in method __str__
to change the default output behavior of the above object.
Next, we will explain the hash overload, object has a __hash__
property, and all objects inherit from object.
print(hash(‘abc‘)) print(hash(123)) # 重载hash方法 class Point: def __hash__(self): return 1 print(hash(Point())): 3225858027842937999: 123: 1
When a hash of an object is hashed using built-in functions, the object's method is called __hash__
. __hash__
method must return an int type. What can a hash method do? What kind of object is a hash?
A hash object is an object that has a __hash__
method. Unless you explicitly set the hash to none,
class Point: __hash__ = None set([Point()]): TypeError: unhashable type: ‘Point‘
If a class has no overriding __hash__
method, each object of this class usually has a different hash. As follows:
class Point: pass p = Point() print(hash(p)) print(id(p)) print(hash(id(p))) p2 = Point() print(hash(p2)) print(id(p2)): 270104426: 4321670816: 4321670816: -9223372036584671309: 4321671992
To give an example of resolving set coordinates,
class Point: def __init__(self, x, y): self.x = x self.y = y def __hash__(self): return hash(‘{}:{}‘.format(self.x, self.y)) p1 = Point(3, 5) p2 = Point(3, 5) # p1, p2都是(3,5)坐标,那么它们应该是相同的对象 # 接下来使用set()去重 print(set([p1, p2])): {<__main__.Point object at 0x102077b38>, <__main__.Point object at 0x102077e80>}
By the above output, we can see that P1 and P2 are different objects.
Special methods for built-in methods and objects
LenOverload
The overloads of Len . When the object implements the Len method, you can use the built-in Len Square
method to find the length of the object. The Len method must return a non-negative integer.
BOOLOverload
- When the object o implements the
__bool__
method, the bool (o) return value is o.__bool__()
.
- When the object o does not implement the
__bool__
method, if O implements the __len__
method, the bool (o) return value is Len (o)! = 0.
- The
__bool__
__len__
bool (o) return value is True when the object o has no methods or methods.
- When the object o is
__bool__
the implementation and __len__
the method, __bool__
the precedence is higher.
__bool__
Method must return a Boolean type.
The above is useful for judging if and while.
Summarize
Today, we mainly introduce the knowledge points of operator overloading in Python, and use the operator overloads in C + + to compare bits. In fact, we also want to let everyone realize that if a certain kind of problem solved, then a lot of similar problems will be solved, truly mastery, follow.
Today the main explanation:
- Python operator overloading
- Python built-in method overloads (brief introduction, later on)
I hope the above content is helpful to everyone. You are welcome to focus on the DevOps Technology Inn.
Python object-oriented operator overloading