3. Magic method
Python's objects naturally have some magical methods. They are always surrounded by double underscores. They are everything of object-oriented python. They are special methods that can add magic to your class. If your object implements (overloads) one of these methods, then this method will be called by Python in a special case. You can define your desired behavior, and all this happens automatically.
All in all, Python's magic method is very powerful.
The following will list these magic methods, and focus on some of the methods.
3.1. Basic magic methods
3.1.1. New and init__
- __The new uuuu method is a real class constructor used to generate instantiated objects (empty properties). Overriding the new method controls the generation of objects.
- __Init method is the initialization method, which is responsible for initializing the property value of the instantiated object. This method must return None, and the new method must return an object. Overriding the init method controls the initialization of the object.
Use new to create a singleton pattern
class Person(object): __instance = None __init_flag = False def __new__(cls, name): if cls.__instance == None: cls.__instance = object.__new__(cls) return cls.__instance else: # Returns a reference to the last created object return cls.__instance def __init__(self,name): if Person.__init_flag == False: self.name = name Person.__init_flag = True
aP = Person('Xiao Ming') print(id(aP)) print(aP.name)
Operation result: 140005334645616 Xiao Ming
bP = Person('Xiao Wang') print(id(bP)) print(bP.name)
Operation result: 140005334645616 Xiao Ming
3.1.2. STR and repr__
The purpose of both is to display some necessary information of the object explicitly, and to facilitate viewing and debugging. __str is called by print by default, and repr is called by console by default. That is, use str to control the user presentation and repr to control the debugging presentation.
class Person: def __init__(self, name, age): self.name = name self.age = age p = Person('Xiao Ming', 26) print(p)
Operation result: <__main__.Person object at 0x7f55883cfd30>
class Person: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return f'{self.__class__}, {self.name}, {self.age}' p = Person('Xiao Ming', 26) print(p)
Operation result: < class'. Person '> Xiaoming, 26
3.1.3.__call__
__The call method provides the ability for an object to be executed, just like a function. In essence, a function is an object, and a function is an object with a call method. For an object with a call method, you can use the call function to get the result of True. You can use () to execute. When executing, you can pass in parameters or return values. So we can use the call method to implement the instantiated object as a decorator:
Object becomes callable
class Person(object): def __init__(self, name): self.name = name def __call__(self, friend): print('My name is %s...' % self.name) print('My friend is %s...' % friend) p = Person('Xiao Ming') p('Xiao Wang')
Operation result: My name is Xiaoming My friend is Xiao Wang
Instance object version decorator
class Checker: def __init__(self, require_num): self.require_num = require_num def __call__(self, func): self.func = func def inner(*args, **kw): if len(args) != self.require_num: print('The number of function parameters does not meet the predefined requirements, unable to execute the function') return None return self.func(*args, **kw) return inner @Checker(2) def show(*args): print('show Function executed successfully!') show(1)
Operation result: The number of function parameters does not meet the predefined requirements, unable to execute the function
3.1.4.__del__
- __del UU is used to call automatically when the reference count of an object is 0.
- __Del_uuuugenerally appears in two places: 1. Manually use del to reduce the object reference count to 0, which is called when it is garbage collected. 2. Called at the end of the program.
- __del? Is generally used to declare resource recovery operations that need to be processed before an object is deleted
Calling del manually can reduce the object reference count by one. If it is reduced to 0, garbage collection will be triggered
class Person: def __del__(self): print('Calling object's del Method, which reclaims the memory address of this object') p = Person() # Call the object's del method to reclaim the object's memory address del p print('There are other codes in the program')
Operation result: Call the del method of the object, which will reclaim the memory address of the object There are other codes in the program
When the program ends directly, it also calls the object's del method to reclaim the address
3.2. Attribute related
The relevant instructions have been described in the descriptor section
- The setattr method of the object is triggered when obj.x = y is used, and the delattr method of the object is triggered when del obj.x is used.
- When an attempt is made to access a nonexistent property of an object, the getattr method is triggered, which has the lowest priority in property lookup.
- If \
- __getatrribute is a property access interceptor, that is, when you access a property, this method will truncate your access behavior and give priority to the code in this method, which should be the highest priority in the property search order.
- Attribute search order: getattribute -- > instance object dictionary of the instance -- > class Dictionary of the instance -- > parent class (MRO order) dictionary of the instance -- > getattr -- > error of the class of the instance
3.3. Comparison operator
class Car(): def __init__(self,carname,oilcp100km, price): self.carname,self.oilcp100km,self.price = carname,oilcp100km, price def __lt__(self,other): print("execute __lt__") return self.price<other.price car1,car2 = Car('Elysee',8,10),Car('Camry',7,27) car1>car2
Operation result: execute __lt__ False
3.4. Arithmetic operator
3.5. Inverse operation
3.6. Incremental assignment
3.7. Unary operator
3.8. Type conversion
3.9. Context management (with statement)
The rewriting of these two methods allows us to use the with method on an object to deal with the preparation before work and the cleaning behavior after work.
class MySQL: def connect(self): print('Start database connection and apply for system resources') def execute(self): print('implement sql Command, operating data') def finish(self): print('Database connection is closed and system resources are cleaned up') def __enter__(self): # Triggered when with and assigned to as variable self.connect() return self def __exit__(self, exc_type, exc_val, exc_tb): # Triggered when leaving the with statement block self.finish() with MySQL() as mysql: mysql.execute()
Operation result: Start database connection and apply for system resources Execute sql command, operate data Database connection is closed and system resources are cleaned up
3.10. Type of container
3.10.1. ITER and next__
These two methods are used to simulate an object into a sequence. Built in types such as lists and tuples can be iterated, and file objects can also be iterated to get each line of content. By overriding these two methods, you can implement a custom iterative object.
Defines a natural number class with a specified range and can provide iteration. Using for loop does not prompt stopinteraction error
class Num: def __init__(self, max_num): self.max_num = max_num self.count = 0 def __iter__(self): return self def __next__(self): if self.count < self.max_num: self.count += 1 return self.count else: raise StopIteration('Has reached the threshold') num = Num(10) for i in num: print(i) # Cycle printing 1-10
Operation result: 1 2 3 4 5 6 7 8 9 10
Use the next() method to iterate one by one, and finally prompt for stopinteraction error
num = Num(2) print(next(num)) print(next(num)) print(next(num))
Operation result: 1 2 --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-18-e4a5cb14ad24> in <module> 2 print(next(num)) 3 print(next(num)) ----> 4 print(next(num)) <ipython-input-15-ac9e7199252c> in __next__(self) 13 return self.count 14 else: ---> 15 raise StopIteration('Has reached the threshold') 16 17 num = Num(10) StopIteration: Has reached the threshold
3.10.2. Getitem, setitem and delete__
Overriding this series of methods can simulate objects into lists or dictionaries, that is, the key value type can be used.
class PersonManager: def __init__(self): self.li = [] self.dic = {} def __getitem__(self, item): if isinstance(item, int): # Get object by subscript return self.dic[self.li[item]] elif isinstance(item, slice): # Slice to get a list of objects start = item.start stop = item.stop return [ self.dic[p] for p in self.li[start:stop]] else: # The given key type is wrong raise TypeError('What you entered key error in type!') def __setitem__(self,key,value): self.li.append(key) self.dic[key]=value class Person: def __init__(self, name): self.name = name def __str__(self): return f'personnel: {self.name}' __repr__ = __str__ pm = PersonManager() pm[0]= Person('Xiao Ming') pm[1]= Person('Great white') pm[2]= Person('Xiaohong') pm[3]= Person('Fat tiger') print(pm[0]) print(pm[0:3])
Operation result: Personnel: Xiao Ming [personnel: Xiaoming, personnel: Dabai, personnel: Xiaohong]
For more articles, please pay attention to: