python Common Magic Method of Double Underline

  • 2021-11-24 02:29:40
  • OfStack

Preface to the table of contents Magic method __init__ method
__new__ method
__call__ method
__str___ method
__del___ method
__enter__ & __exit__ method
item series method
attr series method
Singleton pattern Mode of module import
Through the __new__ method
How to customize metaclasses
Conclusion

Preface

This paper introduces the magic methods commonly used in python under 1 and the singleton pattern which is very important in object-oriented.

Magic method

In python, 1 is an object, because python is an object-oriented programming language. python provides classes and objects with a large number of built-in methods, also known as magic methods. These magic methods are always triggered and executed automatically under certain conditions, just like Magic 1.

__init__ method

This method is used to initialize the null object after receiving the null object returned by the __new__ method in the class when defining the class, and there is no return value.


class Test():
    def __init__(self, name):
        self.name = name
        
    def test(self):
        print(self.name)
   
t = Test('xu')
t1 = Test('python')

__new__ method

This method is firstly triggered when a class is called to instantiate an object. It is used to instantiate an empty object and return.


class Test():
    def __new__(cls , *args, **kwargs):
        return object.__new__(cls, *args, **kwargs) 
    
    def __init__(self, name):
        self.name = name

__call__ method

If you want an object to become a callable object (which can be called in parentheses), you need to define the __call__ method in the object's class, and the return value of calling the callable object is the return value of the __call__ method.


class Test():
    
    def __init__(self):
        self.name = 'python'
    
    def __call__(self, *args, **kwargs):  # self Yes Test Objects of the class 
        print(self)  # <__main__.Test object at 0x000001C78CE78FD0>
        print(self.name)
        
t = Test()
t()  # python

__str___ method

Triggered when an object is accessed for printing, the method must have a return value of type 1 string.


class Test():
    def __init__(self, name):
        self.name = name
 
    def __str__(self):
        return self.name
   
t = Test('xu')
print(t1)  # xu

__del___ method

The __del__ method fires automatically when an object is deleted, Because python's garbage collection mechanism automatically cleans up useless resources in programs, Therefore, if an object only occupies the resources of the application, There is no need to define __del__ method, but if it is designed to occupy system resources, such as open file objects, when the garbage collection mechanism of python is useless because it is related to the resources of the operating system, it is necessary to create __del__ method for the object, which is used to automatically trigger the collection of operating system resources after the object is deleted.


class Test:
    def __init__(self):
        self.x = open('a.txt',mode='w')
        # self.x =  It occupies operating system resources 

    def __del__(self):
        print('run')
        #  Initiate a system call to tell the operating system to recycle related system resources 
        self.x.close()

obj = T()
del obj # obj.__del__() 

__enter__ & __exit__ method

When using with context management, the __enter__ method in the object is triggered and the return value of the __enter__ method is assigned to the variable declared by as.
When with statement ends normally, __exit__ method will be triggered. The three parameters of this method respectively represent exception type, exception value and traceability information. If there is an exception in the code block of with statement, the code after with statement will not be executed. However, if the return value of this method is True, the exception will be cleared and the code after with code block will be executed normally. The code is as follows:


class Open:
    def __init__(self):
        self.name = 'open'

    def __enter__(self):
        print('with The method that is executed first when the statement is executed, and the return value is assigned to the as Declared variables ')
        return self.name

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with Executes when the code block in the exit')
        print(exc_type, ' If an exception occurs, it indicates the exception type ')
        print(exc_val, ' A value representing an exception ')
        print(exc_tb, ' Traceability information representing anomalies ')
        return 123  #  Nonzero   Non-empty   Non None To be true 

    
with Open() as test:
    print(test)
    raise TypeError(' Look 1 Below error message ')
print(' Will I be executed ')  #  When __exit__ Method is executed when the return value of the method is true, otherwise it will not be executed 

item Series Methods

item series methods include __setitem__, __getitem__ and delitem__ methods, which will be triggered when the brackets assign/modify values, take values and delete values respectively. For example, you can customize a dictionary class and customize the methods of assigning, taking values and deleting values with brackets:


class MyDict(dict):

    def __setitem__(self, key, value):
        print(' Execute setitem', key, value)  #  Execute setitem, x, 1
        self.__dict__[key] = value

    def __getitem__(self, item):
        print(' Execute getitem', item)  #  Execute getitem x
        print(self.__dict__[item])  # 1

    def __delitem__(self, key):
        print(' Execute delitem', key)  #  Execute delitem x
        self.__dict__.pop(key)


d = MyDict()
d['x'] = 1
print(d['x'])
del d['x']

attr Series Methods

The attr family of methods includes __setattr__, __getattr__, __delattr__, __setattr__ that are triggered when an attribute is added/modified, __delattr__ that is deleted, and __getattr__ that is triggered when an attribute is invoked and does not exist. As shown in the following code


class Test:
    def __init__(self):
        self.name = 'python'

    def __setattr__(self, key, value):
        print(' Add / Modify attributes setattr')
        self.__dict__[key] = value
        # self.key = value  #  Wireless recursion occurs because the object . Property calls the __setattr__ Method 

    def __delattr__(self, item):
        print(' Delete attribute delattr')
        self.__dict__.pop(item)

    def __getattr__(self, item):
        print(' Called when the property does not exist getattr')
t = Test()
t.x = 'x'
print(t.y)
del t.x

Singleton pattern

Singleton pattern is a software design pattern, in order to ensure that no matter how many times a class is called, the generated objects point to the same memory address, that is, there is only one object.
There are many ways to implement singleton pattern. The general principle is to ensure that a class only instantiates one object, so the key point is how to judge whether this class instantiates one object.

Here are several implementation methods for your reference:

Mode of module import

The principle of this method is that the module is only run once after being imported, and the class in the module is directly searched from memory when being used again later.


# cls_singleton.py
class Foo(object):
    pass

instance = Foo()

# test.py
import cls_singleton

obj1 = cls_singleton.instance
obj2 = cls_singleton.instance
print(obj1 is obj2)  # True

Through the __new__ method

The principle is to judge whether the class has strength, if it has it, it will return directly, and if it does not, it will be saved in _ instance


class Test:

    _instance = None

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __new__(cls, *args, **kwargs):
        # if cls._instance:
        #     return cls._instance                 #  If there is an instance, return it directly 
        # else:
        #     cls._instance = super().__new__(cls) #  If there is no instance, new1 A and save 
        #     return cls._instance                 #  This return is to give or give init And then instantiate 1 Times, it doesn't matter 

        if not cls._instance:                         #  This is a simplified writing method, and the writing method of the above notes is easier to withdraw the judgment ideas 
            cls._instance = super().__new__(cls)
        return cls._instance


t1 = Test('python', 18)
t2 = Test('python1', 18)
print(t1 is t2)  # True

How to customize metaclasses

The principle of this method is the process of class calling. When the class is defined, __init__ under the metaclass will be called, and when the class calls (instantiates the object), the __call__ method under the metaclass will be triggered.


class Test():
    def __new__(cls , *args, **kwargs):
        return object.__new__(cls, *args, **kwargs) 
    
    def __init__(self, name):
        self.name = name
0

Conclusion


Related articles: