Click to jump to the Python Notes home directory
This program recording
A, content,
Second, the role of
Three, use scenarios
Four advantages,
Five, the singleton pattern of four ways to achieve
- 1. Form of file import (common)
- 2. Singleton pattern based on class implementation
- 3. Singleton pattern based on __new__ implementation (most commonly used
- 4. Singleton pattern based on metaclass
Application of singleton pattern (will be used in the database connection pool singleton pattern)
Seven, an additional supplement to the simple profit model with decorators
A, content,
Ensure that a class has only one instance and provide a global access point to access it
Second, the role of
Singletons, that is, only one instance of a class
Three, use scenarios
When a class has only one instance and customers can access it from a well-known point of access such as database links and Socket creation links
Four advantages,
- Controlled access to a unique instance
- Controlled access to a unique instance
Simple interest is equivalent to global variables, but prevents the namespace from being polluted.
Try to ask? Why use singletons instead of global variables?
A. Global variables may have namespace interference and may be overwritten if they have the same name
Five, the singleton pattern of four ways to achieve
1. Form of file import (common)
s1.py
class Foo(object):
def test(self):
print("123")
v = Foo()
#v is an instance of Foo
s2.py
from s1 import v as v1
print(v1,id(v1)) #<s1.Foo object at 0x0000000002221710> 35788560
from s1 import v as v2
print(v1,id(v2)) #<s1.Foo object at 0x0000000002221710> 35788560
The memory address for both is the same
When a file is loaded, it will not be reloaded after the first import.
Copy the code
2. Singleton pattern based on class implementation
# # * * * * * * * * * * * * * * * * * * * * * * the singleton pattern: cannot support multithreading is * * * * * * * * * * * * * * =
class Singleton(object):
def __init__(self):
import time
time.sleep(1)
@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance
import threading
def task(arg):
obj = Singleton.instance()
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
# # * * * * * * * * * * * * * * * * * * * * the singleton pattern: support multithreading is * * * * * * * * * * * * * * * *,
import time
import threading
class Singleton(object):
_instance_lock = threading.Lock()
def __init__(self):
time.sleep(1)
@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
with Singleton._instance_lock: # lock internal for thread safety
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance
def task(arg):
obj = Singleton.instance()
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
time.sleep(20)
obj = Singleton.instance()
print(obj)
Obj = singleton.instance ()
# # example:
## obj1 = Singleton.instance()
## obj2 = Singleton.instance()
## print(obj1,obj2)
## Error example
## obj1 = Singleton()
## obj2 = Singleton()
## print(obj1,obj2)
Copy the code
3. Singleton based on __new__ implementation (most commonly used)
class Singleton:
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls, *args, **kw)
return cls._instance
one = Singleton()
two = Singleton()
two.a = 3
print(one.a)
# # 3
## one is identical to two, and can be detected by id(), **, is
print(id(one))
# # 29097904
print(id(two))
# # 29097904
print(one ** two)
## True
print(one is two)
Copy the code
4. Singleton pattern based on metaclass
"""1. An object is a class creation. When an object is created, its __init__ method is automatically executed, and object () executes its __call__ method 2. Class () executes the __call__ method of type (class __new__ method, class __init__ method). Class Foo: def __init__(self): pass def call__(self, *args, **kwargs): pass ## The __call__ method of type ## 1.1 calls the __new__ method of class Foo (which is an object of type), which is used to create the object. ## 1.2 calls the __init__ method of class Foo (which is an object of type) to initialize the object. Step 2: Execute Foo's __call__ method obj()"""
## **********= execution flow of the class ****************
class SingletonType(type):
def __init__(self,*args,**kwargs):
print(self) # Will it print? #
super(SingletonType,self).__init__(*args,**kwargs)
def __call__(cls, *args, **kwargs): #cls = Foo
obj = cls.__new__(cls, *args, **kwargs)
obj.__init__(*args, **kwargs)
return obj
class Foo(metaclass=SingletonType):
def __init__(self,name):
self.name = name
def __new__(cls, *args, **kwargs):
return object.__new__(cls, *args, **kwargs)
' 'The __init__ () method is automatically executed when the class is created. The __call__ () method is automatically executed when the class is created. Class () first executes the __call__ method of type (calling the __new__, __init__ methods of the class). Foo is created by the SingletonType class.' '
obj = Foo("hiayan")
## ************ The third way to implement the singleton pattern ****************=
import threading
class SingletonType(type):
_instance_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
with SingletonType._instance_lock:
if not hasattr(cls, "_instance"):
cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
return cls._instance
class Foo(metaclass=SingletonType):
def __init__(self,name):
self.name = name
obj1 = Foo('name')
obj2 = Foo('name')
print(obj1,obj2)
Copy the code
Application of singleton pattern (will be used in the database connection pool singleton pattern)
pool.py
import pymysql
import threading
from DBUtils.PooledDB import PooledDB
class SingletonDBPool(object):
_instance_lock = threading.Lock()
def __init__(self):
self.pool = PooledDB(
creator=pymysql, ## Use the link database module
maxconnections=6, ## The maximum number of connections allowed by the pool. 0 and None indicate that the number of connections is not limited
mincached=2, At least one free link was created in the link pool during initialization. 0 means no link was created
maxcached=5, ## The maximum number of idle links in the link pool, 0 and None are not limited
maxshared=3,
## The maximum number of links shared in the link pool. 0 and None indicate all links. PS: useless because modules such as Pymysql and MySQLdb have threadsafety of 1 and _maxcached is always 0 no matter what the value is set to, so all links are always shared.
blocking=True, If there is no connection available in the connection pool, whether to block waiting. True c. False, do not wait and then report an error
maxusage=None, ## The maximum number of times a link can be reused. None means unlimited
setsession=[], ## List of commands to execute before starting a session. ["set datestyle to...", "set time zone..."]
ping=0,
Ping MySQL server to check whether the service is available. # #, such as: 0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='pooldb',
charset='utf8'
)
def __new__(cls, *args, **kwargs):
if not hasattr(SingletonDBPool, "_instance"):
with SingletonDBPool._instance_lock:
if not hasattr(SingletonDBPool, "_instance"):
SingletonDBPool._instance = object.__new__(cls, *args, **kwargs)
return SingletonDBPool._instance
def connect(self):
return self.pool.connection()
Copy the code
app.py
from pool import SingletonDBPool
def run():
pool = SingletonDBPool()
conn = pool.connect()
## xxxxxx
cursor = conn.cursor()
cursor.execute("select * from td where id=%s", [5, ])
result = cursor.fetchall() ## Get data
cursor.close()
conn.close()
if __name__ ** '__main__':
run()
Copy the code
An additional singleton pattern implemented with decorators
#
def wrapper(cls):
instance = {}
def inner(*args,**kwargs):
if cls not in instance:
instance[cls] = cls(*args,**kwargs)
return instance[cls]
return inner
@wrapper
class Singleton(object):
def __init__(self,name,age):
self.name = name
self.age = age
obj1 = Singleton('haiyan',22)
obj2 = Singleton('xx', 22)print(obj1)
print(obj2)
Copy the code