“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”
Wechat public number search [program yuan xiaozhuang], concerned about halfway out of the program yuan how to rely on Python development to make a living ~
preface
This article introduces the magic methods commonly used in Python and the singleton pattern, which is very important in object orientation.
Magic methods
Everything in Python is an object, because Python is an object-oriented programming language. Python provides a large number of built-in methods for classes and objects. These built-in methods are also called magic methods. These magic methods are always automatically triggered under certain conditions, just like magic.
__init__
methods
This method is used to initialize an empty object that is returned by the __new__ method of the class when the class is defined. It returns no value.
class Test() :
def __init__(self, name) :
self.name = name
def test(self) :
print(self.name)
t = Test('xu')
t1 = Test('python')
Copy the code
__new__
methods
This method is the first to be triggered when a class is called to instantiate an object. It is used to instantiate an empty object and return.
class Test() :
def __new__(* * kwargs CLS, * args) :
return object.__new__(cls, *args, **kwargs)
def __init__(self, name) :
self.name = name
Copy the code
__call__
methods
If you want an object to become a callable, you need to define a __call__ method in the object’s class. The value returned by calling the callable object is the value returned by __call__.
class Test() :
def __init__(self) :
self.name = 'python'
def __call__(self, *args, **kwargs) : # self is an object of class Test
print(self) # <__main__.Test object at 0x000001C78CE78FD0>
print(self.name)
t = Test()
t() # python
Copy the code
__str___
methods
To trigger execution when the object is accessed for printing, the method must have a return value of type string.
class Test() :
def __init__(self, name) :
self.name = name
def __str__(self) :
return self.name
t = Test('xu')
print(t1) # xu
Copy the code
__del___
methods
The __del__ method is triggered when an object is deleted. Since Python’s garbage collection mechanism automatically clears unused resources from the program, there is no need to define a __del__ method if an object is designed to occupy only application resources, but if it is designed to occupy system resources such as open file objects, When Python’s garbage collection mechanism is not useful for operating system resources, it is necessary to create a __del__ method for an object that automatically triggers the collection of operating system resources when the object is deleted.
class Test:
def __init__(self) :
self.x = open('a.txt',mode='w')
# self.x = Use the operating system resource
def __del__(self) :
print('run')
Make a system call telling the operating system to reclaim the system resources
self.x.close()
obj = T()
del obj # obj.__del__()
Copy the code
__enter__ & __exit__
methods
When using with context management, the __enter__ method in the object is fired and the return value of the __enter__ method is assigned to the variable declared by as.
When the with statement ends normally, the __exit__ method is fired. The three arguments to the __exit__ method represent the exception type, the exception value, and the traceability information. If the with block contains an exception, the code after the with statement is not executed, but if the method returns True, the exception is cleared. The code after the with block will execute normally. The code is as follows:
class Open:
def __init__(self) :
self.name = 'open'
def __enter__(self) :
print('The first method to be executed when the with statement is executed, and the return value is assigned to the variable declared by as.')
return self.name
def __exit__(self, exc_type, exc_val, exc_tb) :
print(Execute exit when the block in 'with 'finishes executing.)
print(exc_type, 'If an exception occurs, indicate the exception type')
print(exc_val, 'Value that represents an exception')
print(exc_tb, 'Indicates traceability information for the exception')
return 123 # Non-zero non-empty Non-none is true
with Open() as test:
print(test)
raise TypeError('Look at the error message')
print('Am I going to be executed?') When __exit__ returns true, it will be executed, otherwise it will not be executed
Copy the code
item
Series method
The item family of methods includes __setitem__, __getitem__, and delItem__ methods, which are triggered when the brackets assign/modify, the brackets value, and the brackets delete values, respectively. For example, you can customize a dictionary class and customize the brackets assign, value, and delete methods:
class MyDict(dict) :
def __setitem__(self, key, value) :
print('execution setitem', key, value) Setitem, x, 1
self.__dict__[key] = value
def __getitem__(self, item) :
print('perform the getitem', item) Getitem x
print(self.__dict__[item]) # 1
def __delitem__(self, key) :
print('execution delitem', key) # Delitem x
self.__dict__.pop(key)
d = MyDict()
d['x'] = 1
print(d['x'])
del d['x']
Copy the code
attr
Series method
The attr family of methods includes __setattr__,__getattr__,__delattr__, __setattr__ when adding/modifying attributes, ___delattr__ when removing attributes, and __getattr__ when in use. Triggered when a property is called and does not exist. The following code is shown
class Test:
def __init__(self) :
self.name = 'python'
def __setattr__(self, key, value) :
print('Add/modify property setattr')
self.__dict__[key] = value
# self.key = value # will cause wireless recursion because the object. Property calls the __setattr__ method
def __delattr__(self, item) :
print('Delete property delattr')
self.__dict__.pop(item)
def __getattr__(self, item) :
print('Call getattr if the property does not exist')
t = Test()
t.x = 'x'
print(t.y)
del t.x
Copy the code
The singleton pattern
Singleton pattern is a software design pattern to ensure that no matter how many times a class is called, the generated object points to the same memory address, that is, only one object.
There are many ways to implement the singleton pattern. The general principle is to ensure that a class instantiates only one object, so the key is how to determine if the class has instantiated an object.
Here are several implementation methods for your reference:
Module import mode
The principle of this method is that after the module is imported, it will only run once, and then use the classes in the module again is directly from memory.
# 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
Copy the code
through__new__
methods
The principle is to determine whether the class has strength, if there is direct return, not saved to _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 # return cls._instance
# else:
# cls._instance = super().__new__(CLS) #
# return cls._instance # return cls._instance # Return cls._instance # Return cls._instance # Return cls._instance #
if not cls._instance: # This is a simplified way to write, the above comments write method is easier to withdraw judgment train of thought
cls._instance = super().__new__(cls)
return cls._instance
t1 = Test('python'.18)
t2 = Test('python1'.18)
print(t1 is t2) # True
Copy the code
How to customize metaclasses
The principle of this approach is the process of class invocation, which calls __init__ under the metaclass when the class is defined, and __call__ under the metaclass when the class is called (instantiating the object).
class Mymeta(type) :
def __init__(cls, name, bases, dic) :
super().__init__(name, bases, dic)
cls._instance = None The data properties of the instance object of the record class are automatically defined in the metaclass
def __call__(cls, *args, **kwargs) : # This call is triggered when the class is called (i.e. instantiated)
if cls._instance: # Determine if the class instantiates an object
return cls._instance
else: When no object is instantiated, the control class creates an empty object and initializes it
obj = cls.__new__(cls, *args, **kwargs)
obj.__init__(*args, **kwargs)
cls._instance = obj # Save the object, and the next instantiation can return directly without re-creating the object
return obj
class Test(metaclass=Mymeta) :
def __init__(self, name, age) :
self.name = name
self.age = age
t1 = Test('python'.18)
t2 = Test('python1'.18)
print(t1 is t2) # True
Copy the code
conclusion
The article was first published in the wechat official account program Yuan Xiaozhuang, and was synchronously published in Digijin and Zhihu.
Please explain where it came from. If you pass by, please put out your cute little finger and click like before you go (╹▽╹)