单例

什么是单例?

 单例模式是指:保证一个类仅有一个实例,并提供一个访问它的全局访问点

# 线程1 执行:
cursor.excute('select * from user')

# 线程2执行 
cursor.excute('select * from books')

# 线程1 执行
cursor.fetchAll() # 拿出查询到的数据

# django ,每个线程,一个连接对象---》 连接池

1. 使用模块

  其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:

mysingleton.py:

class Singleton(object):
    def foo(self):
        pass
singleton = Singleton()

将上面的代码保存在文件 mysingleton.py 中,要使用时,直接在其他文件中导入此文件中的对象,这个对象即是单例模式的对象

from a import singleton 
# 不论在哪个py文件中导入singleton ,都是同一个singleton对象

2. 使用装饰器

1. 闭包函数是什么?

  参数是传不进来的,是包进来的,用了它上层作用域范围的变量

  -1. 定义在函数内部

  -2. 对外部作用域有引用(如果使用外部的可变类型,直接使用,如果是不可变类型,需要使用nonlocal声明)

def add():
    # a = 1   不可变类型
    a = [1,2,3] # 可变类型,直接使用
    def inner():
        # nonlocal a 需要声明使用
        a.append('ss')
        print('内部的值是:',a)
    inner()
    print('外部的值',a)

add()    

2. 装饰器是什么?

  - 装饰器是闭包函数的一个典型应用,在实现不改变函数的源代码和调用方式的基础上,为函数增加新的功能

3. 装饰器的作用?

  - 在实现不改变函数的源代码和调用方式的基础上,给函数增加新的功能

比如:

import time
def time_total(func):
    def inner(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print('运行时间是:', end - start)
        return res

    return inner

@time_total  # 原理就是   add=time_total(add)
def add(a, b):
    time.sleep(2)
    return a + b

res=add(2,3) # 现在是inner
print(add.__name__)  # 函数名

使用装饰器来实现单例:

### 2 方式二:使用装饰器
## 之前学的 装饰器,都是用来装饰 函数  ,装饰器可以用来装饰类
def singleton(cls):
    instance = None
    def _singleton(*args, **kargs):
        nonlocal instance
        if not instance:
            instance = cls(*args, **kargs)
        return instance

    return _singleton

@singleton    # A=singleton(A)
class A():
    def __init__(self, x=0):
        self.x = x

a1 = A(2)  # 其实执行的是 singleton内部的闭包函数 _singleton()
a2 = A(3)

print(a1 is a2) # True

3. 使用类方法

## 方式三: 使用类方法
class Singleton(object):
    _instance = None

    def __init__(self):
        pass

    @classmethod
    def instance(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = cls(*args, **kwargs)
        return cls._instance


a1 = Singleton.instance()  # 对象=类.类的绑定方法
a2 = Singleton.instance()

print(a1 is a2)

4. 基于new方法实现

### 方式四:使用 __new__
class Singleton(object):
    _instance = None

    def __init__(self):
        pass

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls)
        return cls._instance


obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2)

5. 基于metaclass方式实现

class SingletonType(type):
    _instance = None

    def __call__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls)
            cls._instance.__init__(*args, **kwargs)
        return cls._instance


class Foo(metaclass=SingletonType):
    def __init__(self, name):
        print('sdfasdf')
        self.name = name


obj1 = Foo('name')
obj2 = Foo('name')
print(obj1 is obj2)

__init__ 和 __new__区别

1.  类()--->触发类中的__init__--->对象已经创建出来了,不能拦截住,做成单例了

2. 类()--->触发类中的__new__--->真正的创建对象,判断之前有没有创建过,如果创建过,直接返回

3. 懂了元类---》类()--->触发元类的 __call__--->断之前有没有创建过,如果创建过,直接返回

 

posted @ 2023-10-18 21:30  Maverick-Lucky  阅读(11)  评论(0)    收藏  举报