Reference link :
Python Realization and optimization of singleton pattern in - Listen to the wind . - Blog Garden
The singleton pattern (Singleton Pattern) Is a common software design pattern , The main purpose of this model is to ensure that There is only one instance of a class . When you want to be in the whole system , When only one instance of a class can appear , A single object can be used .
such as , The configuration information of a server program is stored in a file , Client through a AppConfig Class to read configuration file information . If during the program run , There are a lot of places where you need to use the content of a profile , in other words , Many places need to create AppConfig Instance of object , This results in multiple AppConfig Instance object of , And this is a serious waste of memory resources , Especially when the configuration file has a lot of content . in fact , similar AppConfig Such a class , We want to have only one instance object during program execution .
stay Python in , There are many ways to implement singleton patterns
The configuration file configuration.yml
DB:
host: 1
username: 12
password: 12
database: 14
databasetype: 15
port: 33
note: C
The class that stores the configuration file MyDbinfo
import yaml
class MyDbinfo(object):
def __init__(self):
_filePath = "/Users/zhaohui/PycharmProjects/TestSingleton/configuration.yml"
f = open(_filePath, 'r', encoding='utf-8')
cont = f.read()
x = yaml.load(cont, Loader=yaml.FullLoader)
self.host =x['DB']['host']
self.username=x['DB']['username']
self.password=x['DB']['password']
self.database=x['DB']['database']
self.port=x['DB']['port']
self.note = x['DB']['note']
Now create 2 individual MyDbinfo Example
myDbinfo1 = MyDbinfo()
myDbinfo2 = MyDbinfo()
if __name__ == '__main__':
print(myDbinfo1)
print(myDbinfo2)
Print the results :
<MyDbinfo.MyDbinfo object at 0x7fcc580f4290>
<MyDbinfo.MyDbinfo object at 0x7fcc48021850>
Print the results , yes 2 Different physical addresses , The instance we created , yes 2 Different instances . Will consume memory resources .
Actually ,Python The module is a natural singleton mode , Because when the module is first imported , Will generate .pyc
file , When the second import , It will load directly .pyc
file , Instead of executing the module code again . therefore , We just need to define the relevant functions and data in one module , You can get a singleton object . If we really want a singleton class , Consider doing so :
MyDbinfo.py
import yaml
class MyDbinfo(object):
def __init__(self):
_filePath = "/Users/zhaohui/PycharmProjects/TestSingleton/configuration.yml"
f = open(_filePath, 'r', encoding='utf-8')
cont = f.read()
x = yaml.load(cont, Loader=yaml.FullLoader)
self.host =x['DB']['host']
self.username=x['DB']['username']
self.password=x['DB']['password']
self.database=x['DB']['database']
self.port=x['DB']['port']
self.note = x['DB']['note']
myDbinfo = MyDbinfo()
Save the above code in a file MyDbinfo.py in , To use , Import objects in this file directly into other files , This object is the object of singleton pattern
establish 2 An example
from MyDbinfo import myDbinfo
myDbinfo1 = myDbinfo
myDbinfo2 = myDbinfo
if __name__ == '__main__':
print(myDbinfo1)
print(myDbinfo2)
Print the results :
<MyDbinfo.MyDbinfo object at 0x7fc078111b90>
<MyDbinfo.MyDbinfo object at 0x7fc078111b90>
Is a singleton
singleton.py
def singleton(cls,*args,**kw):
instances = {}
def _singleton():
if cls not in instances:
instances[cls] = cls(*args,**kw)
return instances[cls]
return _singleton
MyDbinfo class , Add comments for the singleton pattern
MyDbinfo.py
import yaml
from singleton import singleton
@singleton
class MyDbinfo(object):
def __init__(self):
_filePath = "/Users/zhaohui/PycharmProjects/TestSingleton/configuration.yml"
f = open(_filePath, 'r', encoding='utf-8')
cont = f.read()
x = yaml.load(cont, Loader=yaml.FullLoader)
self.host =x['DB']['host']
self.username=x['DB']['username']
self.password=x['DB']['password']
self.database=x['DB']['database']
self.port=x['DB']['port']
self.note = x['DB']['note']
Start testing
from MyDbinfo import MyDbinfo
myDbinfo1 = MyDbinfo()
myDbinfo2 = MyDbinfo()
if __name__ == '__main__':
print(myDbinfo1)
print(myDbinfo2)
Print the results :
<MyDbinfo.MyDbinfo object at 0x7fcd50154290>
<MyDbinfo.MyDbinfo object at 0x7fcd50154290>
This is a single example .
How to achieve it :
1、 You need to know about decorators first :
python Closures and decorators _ Proud cat sauce blog -CSDN Blog
2、 We just need to focus on this piece of logic
3、 Inside cls Is our decorated function
4、_instance It's an empty dictionary
5、 If the decorated function , Not in the dictionary , Then we will cls() Create an instance . Put it in the dictionary , then return get out .
If the decorated function , In the dictionary , direct return Get out of this instance .
6、 The function of closures is to make a variable resident in memory .
be _instance = {} It's memory resident ( That's the point )
② Keep the local variables inside the function in memory all the time :
How to understand this sentence ? Generally speaking , The local variables inside the function after the function is run , Will be Python The garbage collection mechanism of is cleared from memory . If we want this local variable to be stored in memory for a long time , Then you can use closures to implement this function .
Borrow here
@ A thousand mountains of snow
Example ( From : A thousand mountains of snow : Explain profound theories in simple language python Closure ). Look at the code below .
Take an example similar to a board game to illustrate . Suppose the size of the chessboard is 50*50, The upper left corner is the origin of the coordinate system (0,0), I need a function , receive 2 Parameters , The directions are (direction), step (step), This function controls the movement of the chess pieces . Here's the thing to note , The starting point of each movement is the end point of the last movement .
def create(pos=[0,0]):
def go(direction, step):
new_x = pos[0]+direction[0]*step
new_y = pos[1]+direction[1]*step
pos[0] = new_x
pos[1] = new_y
return pos
return go
player = create()
print(player([1,0],10))
print(player([0,1],20))
print(player([-1,0],10))
In this code ,player It's actually a closure go An instance object of the function .
It ran three times , The first is along X The axis is moving forward 10 Came to [10,0], The second time is along Y The axis is moving forward 20 Came to [10, 20],, The third time is in the opposite direction X The shaft retreated 10 Came to [0, 20].
This proves , function create Local variable in pos Keep it in memory all the time , Not in create It is automatically cleared after calling .
Why is this so ? And the reason is that create yes go The parent function of , and go Is assigned a global variable , This leads to go Always in memory , and go Is dependent on create, therefore create It's always in memory , Not after the call , Garbage collection mechanism (garbage collection) Recycling .
This is the time , Closures make the internal variables of an instance object of a function , Become very much like the properties of an instance object of a class , Can always be saved in memory , And constantly calculate it .