Refer to the official documents of python3.7
Basic method
__class__
See__ name__
__name__
1) Current module name, of the directly running module__ name__ Is'__ main__‘, Other modules are 'module name' or 'package name. Module name'
# tmpPkg.tmp.py print(f'tmp.py {__name__}') # main.py import tmpPkg.tmp print(f'main.py {__name__}') > python .\main.py tmp.py tmpPkg.tmp main.py __main__
2) Object class name or function name
class TestC: pass def testM(): pass print(type(TestC())) print(TestC().__class__) # <class '__main__.TestC'> # <class '__main__.TestC'> print(type(TestC()).__name__) print(TestC().__class__.__name__) # TestC # TestC print(testM.__name__) # testM
__call__(self[, args...])
class Test: def __call__(self, __x, __y): return f'{__x} + {__y} = {__x + __y}' t = Test() print(t(3, 5)) # 3 + 5 = 8
__new__(cls[, ...])
See__ del__(self)
__init__(self[, ...])
See__ del__(self)
__del__(self)
new create object, static method (special here, don't mark @staticmethod)
*The new method needs to return an instance of cls. The general writing is: return super() New (cls, *args, *kwargs), otherwise__ init__ Function will not execute)
Init initializes the object, and also pay attention to calling the parent class__ init__ method
Del destroy object (not recommended): called when the reference number is 0 to destroy the object. If the parent class contains del methods, pay attention to calling the Del methods of the parent class (object class has no del methods)
Execution order: code block new method init method... del method
class Test: print('Execute code block') def __new__(cls, *args, **kwargs): print('implement new') return super().__new__(cls, *args, **kwargs) def __init__(self): print('implement init') super(Test, self).__init__() def __del__(self): print('implement del') # If the parent class contains del methods, pay attention to calling the Del methods of the parent class (object class has no del methods), so do not call them here # super(Test, self).__del__() Test() # Execute code block # Execute new # Execute init # Execute del
__repr__(self)
See__ str__(self)
__str__(self)
__ repr__: The 'formal string' describing the object is usually used for debugging, so it is informative and clear.
__ str__: The 'informal string' describing the object is usually printed, so it is convenient to represent the brief introduction of information. If__ str__ Not implemented but__ repr__ Implement, then__ str__ Will use__ repr__ Returned string
class Test: def __repr__(self): return 'aaa' def __str__(self): return 'bbb' t = Test() print(repr(t)) print(str(t)) print(t) # Not implemented__ repr__, Not implemented__ str__ # <__main__.Test object at 0x000002056CEEF588> # <__main__.Test object at 0x000002056CEEF588> # <__main__.Test object at 0x000002056CEEF588> # Implementation__ repr__, Not implemented__ str__ # aaa # aaa # aaa # Not implemented__ repr__, Implementation__ str__ # <__main__.Test object at 0x00000228D90B8608> # bbb # bbb # Implementation__ repr__, Implementation__ str__ # aaa # bbb # bbb
__bytes__(self)
See__ bool__(self)
__bool__(self)
__ bytes__: Convert the object to bytes and call through bytes(x)
__ bool__: Returns True/False, if__ bool__ If not, call__ len__ Method, so the values of [] (empty list), () (empty tuple), '(or' ', empty string), {} (empty set or empty dictionary) are False. In addition, the defined False values include False (standard true value), None, and 0.
class Test: def __bytes__(self): return b'x01x02' def __bool__(self): return True # Implementation__ bytes__ t = Test() print(bytes(t)) # b'x01x02' print(bool(t)) # True
__fspath__(self)
Return the path str of the file system where the object is located
import os class Test: def __fspath__(self): return 'home/malloclu/TestObject' print(os.fspath(Test())) # home/malloclu/TestObject
(shallow) replication and deep replication
Type already exists
Copy (shallow) copy, deepcopy deep copy
from copy import copy, deepcopy # Basic data type a = 1.2 # 1. Quotation b1 = a # 2. (shallow) copy b2 = copy(a) # 3. Deep copy b3 = deepcopy(a) a = 3.4 # Because the basic data type has only assignment and no reference, the values of the three methods have not changed print(f'{b1}\n{b2}\n{b3}\n') # 1.2 # 1.2 # 1.2 # Simple objects (such as single-layer containers) a = [1, 2, 3] # 1. Quotation b1 = a # 2. (shallow) copy b2 = copy(a) # 3. Deep copy b3 = deepcopy(a) a[1] = 4 # Only the reference method value has changed, because it and a point to the same object in memory print(f'{b1}\n{b2}\n{b3}\n') # [1, 4, 3] # [1, 2, 3] # [1, 2, 3] # Multi tier containers (e.g. multi tier containers, dictionary nested lists) a = {'k': [1, 2, 3]} # 1. Quotation b1 = a # 2. (shallow) copy b2 = copy(a) # 3. Deep copy b3 = deepcopy(a) a['k'][1] = 4 # The values of reference b1 and (shallow) copy b2 have changed. Among them, b1 refers to the same object in memory as a, b2 refers to the dictionary key generated by shallow copy to [1, 2, 3] of a, and b3 refers to the newly generated dictionary key generated by deep copy to [1, 2, 3]. print(f'{b1}\n{b2}\n{b3}\n') # {'k': [1, 4, 3]} # {'k': [1, 4, 3]} # {'k': [1, 2, 3]}
memo
The memory id to object correspondence is preserved in the memo dictionary in order to reconstruct the complex object graph perfectly. (if you don't want to know the corresponding relationship, this parameter can not be used when deepcopy(x, memo={}) is used)
from copy import deepcopy a = {'k': [1, 2, 3]} memo={} b = deepcopy(a, memo=memo) print(memo) # {2092202719048: [1, 2, 3], # 2092195593896: {'k': [1, 2, 3]}, # 2092195593976: [[1, 2, 3], {'k': [1, 2, 3]}]}
Custom type
(shallow) replication and deep replication should be implemented separately__ copy__(self) and__ deepcopy__(self, memodict={}) method
from copy import copy, deepcopy class Test: def __init__(self, val): self.val = val def __copy__(self): return Test(self.val) def __deepcopy__(self, memodict={}): return Test(deepcopy(self.val, memodict)) def __str__(self): return str(self.val) # Simple objects (such as single-layer containers) a = Test([1, 2, 3]) # 1. Quotation b1 = a # 2. (shallow) copy b2 = copy(a) # 3. Deep copy b3 = deepcopy(a) a.val[1] = 4 # The values of reference b1 and (shallow) copy B2 have changed. Among them, b1 and a point to the same object in memory, B2 because b2.val and a.val point to the same object in memory, and B3 because b3.val points to the newly generated [1, 2, 3]. print(f'{b1}\n{b2}\n{b3}\n') # [1, 4, 3] # [1, 4, 3] # [1, 2, 3]
Operator overloading
Binary operator
Method list
Symbol | operation | Inverse operation | Incremental assignment operation (e.g. + =, - = etc.) | remarks |
---|---|---|---|---|
+ | __add__(self, other) | __iadd__(self, other) | __radd__(self, other) | |
- | __sub__(self, other) | __isub__(self, other) | __rsub__(self, other) | |
* | __mul__(self, other) | __imul__(self, other) | __rmul__(self, other) | |
@ | __matmul__(self, other) | __imatmul__(self, other) | __rmatmul__(self, other) | numpy type implements this method, that is, matrix multiplication, basic data type and list are not implemented |
/ | __truediv__(self, other) | __itruediv__(self, other) | __rtruediv__(self, other) | divide |
// | __floordiv__(self, other) | __ifloordiv__(self, other) | __rfloordiv__(self, other) | Divide by |
% | __mod__(self, other) | __imod__(self, other) | __rmod__(self, other) | |
divmod(__x, __y) | __divmod__(self, other) | __rdivmod__(self, other) | Return (quotient, remainder) | |
** | __pow__(self, other[, modulo]) | __ipow__(self, other[, modulo]) | __rpow__(self, other[, modulo]) | modulo is complemented by the other power of self or the other power of self |
<< | __lshift__(self, other) | __ilshift__(self, other) | __rlshift__(self, other) | Shift left |
>> | __rshift__(self, other) | __irshift__(self, other) | __rrshift__(self, other) | Shift right |
& | __and__(self, other) | __iand__(self, other) | __rand__(self, other) | Bitwise AND |
^ | __xor__(self, other) | __ixor__(self, other) | __rxor__(self, other) | Bitwise XOR |
` | ` | __or__(self, other) | __ior__(self, other) | __ror__(self, other) |
< | __lt__(self, other) | |||
<= | __le__(self, other) | |||
== | __eq__(self, other) | |||
!= | __ne__(self, other) | |||
> | __gt__(self, other) | |||
>= | __ge__(self, other) |
Operation & inverse operation
Take + as an example. A + B requires that a is overloaded__ add__ Operator or B overloaded__ radd__ Operator (if both are overloaded, use a's _uadd _uoperator) [code 1]
In overloaded operator methods, the type of another operand should be judged, and an exception should be thrown manually when no code is written for this type [code 2]
(for example, A+B, A belongs to classA, B belongs to classB, and A overloads the _add_method. When executing A+C (C belongs to classC), A can also call the__ add__ Method, but A's__ add__ The function body is written for classB, so it is likely that various exceptions will occur when the execution fails. Therefore, it is recommended to use A__ add__ In the function body, first judge the type of another operand, write different operations for different types, and manually throw exceptions for types that are not considered.)
class TestA: def __add__(self, other): return f'add TestA + {type(other).__name__}' class TestB: pass class TestC: def __radd__(self, other): return f'radd {type(other).__name__} + TestC' # Left operand overloaded__ add__, Will be called, and there is no requirement for overload of right operation print(TestA() + TestA()) print(TestA() + TestB()) print(TestA() + TestC()) print(TestA() + 1) # add TestA + TestA # add TestA + TestB # add TestA + TestC # add TestA + int # Left operand not overloaded__ add__, If the right operation is overloaded__ radd__ Will be called, otherwise an error will be reported print(TestB() + TestA()) print(TestB() + TestB()) print(TestB() + TestC()) print(TestB() + 1) # TypeError: unsupported operand type(s) for +: 'TestB' and 'TestA' # TypeError: unsupported operand type(s) for +: 'TestB' and 'TestB' # radd TestB + TestC # TypeError: unsupported operand type(s) for +: 'TestB' and 'int'
# Not recommended class TestA: def __add__(self, other): if isinstance(other, int): return f'add TestA + {type(other).__name__}' print(TestA() + 1) print(TestA() + 'tmp') # add TestA + int # None # **Recommend** class TestB: def __add__(self, other): if isinstance(other, int): return f'add TestA + {type(other).__name__}' raise TypeError(f"unsupported operand type(s) for +: 'TestA' and '{type(other).__name__}'") print(TestB() + 1) print(TestB() + 'tmp') # add TestA + int # TypeError: unsupported operand type(s) for +: 'TestA' and 'str'
Incremental assignment operation
class TestA: def __init__(self, val): self.val = val def __add__(self, other): if isinstance(other, TestA): return TestA(self.val + other.val) raise TypeError(f"unsupported operand type(s) for +: 'TestA' and '{type(other).__name__}'") A = TestA(1) B = TestA(2) C = A + B print(C.val) class TestB: def __init__(self, val): self.val = val def __iadd__(self, other): if isinstance(other, TestB): return TestB(self.val + other.val) raise TypeError(f"unsupported operand type(s) for +: 'TestB' and '{type(other).__name__}'") A = TestB(4) B = TestB(5) A += B print(A.val)
Unary operator
Method list
Symbol | method | remarks |
---|---|---|
- | __neg__(self) | Positive, return any type |
+ | __pos__(self) | Take negative, return any type |
abs(__x) | __abs__(self) | Absolute value, any return type |
~ | __invert__(self) | Negate by bit, return any type |
complex(__x) | __complex__(self) | Convert to complex number and return the complex type, such as 1+2j |
int() | __int__(self) | Convert to integer and return integer type, such as 3 |
float() | __float__(self) | Convert to floating-point number and return the floating-point number type, such as 4.5 |
Automatic call | __index__(self) | This function is automatically called where an integer is required to convert the object to an integer type, such as when it is used as an index of a list slice. |
round(__x, ndigits=0) | __round__(self[, ndigits]) | Round to the nearest and return any type. The implemented int type result is an integer multiple of 10^(-ndigits) (ndigits defaults to 0, and the result defaults to an integer multiple of 1, that is, rounding), round(0.5) is 0, and round(0.50001) is 1. |
math.trunc(__x) | __trunc__(self) | Truncate and round, and the return type is arbitrary. The implemented int type math.trunc(-2.3) is -2. |
math.floor(__x) | __floor__(self) | Round down and return any type. The implemented int type math.floor(-2.3) is -3. |
math.ceil(__x) | __ceil__(self) | Round up and return any type. The implemented int type math.ceil(-2.7) is -2. |
Example
import math class Test: def __neg__(self): return 'a' def __pos__(self): return 'b' def __abs__(self): return 'c' def __invert__(self): return 'd' def __complex__(self): return 1 + 2j def __int__(self): return 3 def __float__(self): return 4.5 def __index__(self): return 1 def __round__(self, n=None): return 'e' def __trunc__(self): return 'f' def __floor__(self): return 'g' def __ceil__(self): return 'h' print(-Test()) print(+Test()) print(abs(Test())) print(~Test()) # a # b # c # d print(complex(Test())) print(int(Test())) print(float(Test())) # (1+2j) # 3 # 4.5 testlist = ['aa', 'bb', 'cc'] print(testlist[Test()]) print(testlist[Test():Test()]) # bb # [] print(round(Test())) print(math.trunc(Test())) print(math.floor(Test())) print(math.ceil(Test())) # e # f # g # h
iterator
__ next__ Return the next value of the iterator object (if no StopIteration exception is thrown). If this method is implemented, the object can continuously return the next value as a parameter of next(__x)
__ iter__ Return an iterator object (the class to which the object belongs has implemented the \u next \u method). If this method is implemented, the object can iterate in the for loop and constantly return the next value
class Fibs: def __init__(self): self.a = 0 self.b = 1 def __next__(self): self.a, self.b = self.b, self.a + self.b return self.a def __iter__(self): return self >>>fibs = Fibs() >>>next(fibs) 1 >>>next(fibs) 2 >>>for f in fibs: ... if f > 1000: ... print(f) ... break 1597
cle/details/111863037)
__ next__ Return the next value of the iterator object (if no StopIteration exception is thrown). If this method is implemented, the object can continuously return the next value as a parameter of next(__x)
__ iter__ Return an iterator object (the class to which the object belongs has implemented the \u next \u method). If this method is implemented, the object can iterate in the for loop and constantly return the next value
class Fibs: def __init__(self): self.a = 0 self.b = 1 def __next__(self): self.a, self.b = self.b, self.a + self.b return self.a def __iter__(self): return self >>>fibs = Fibs() >>>next(fibs) 1 >>>next(fibs) 2 >>>for f in fibs: ... if f > 1000: ... print(f) ... break 1597