程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python singleton mode

編輯:Python

  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

One 、 scene :

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 .

Two 、 Several ways to realize singleton mode

1. Using modules

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

2. Use decorators

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 .


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved