Python 中,单例模式的5种实现方式(使用模块、使用装饰器、使用类方法、基于new方法实现、基于metaclass方式实现)

单例模式的5种实现方式
1 使用模块
2 使用装饰器
3 使用类方法
4.基于new方法实现
5 基于metaclass方式实现

单例模式的5种实现方式

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

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

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

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

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

1 使用模块

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

1.新建一个mysingleton.py
 class Singleton(object):
      def foo(self):
          pass
  singleton = Singleton()

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

2 使用装饰器

   def Singleton(cls):
        instance = None
        def _singleton(*args, **kargs):
            nonlocal instance
            if not instance:
                instance = cls(*args, **kargs)
            return instance
        return _singleton
    
    @Singleton
    class A(object):
        def __init__(self, x=0):
            self.x = x

    a1 = A(2)
    a2 = A(3)
    print(a1.x)
    print(a2.x)
    
    print(a1 is a2)  # True
    

回顾装饰器是什么


import time

# 装饰器是什么?装饰器的作用是什么?
'''
装饰器是闭包函数的一个典型应用

它是什么?
    在不改变函数源代码和调用方式idea基础上,为函数增加新功能
'''


# def add(a, b):
#     time.sleep(2)
#     return a + b


def time_total(func):
    def inner(a, b):
        start = time.time()
        res = func(a, b)
        print('运行时间是:', time.time() - start)
        return res

    return inner


# add = time_total(add)
# res = add(3, 4)
# print(res)


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


res = add(3, 4)
print(res)
print(add.__name__)  # 就是inner

# 什么是闭包函数?参数不是传进来的,是用了它上一层作用域范围的变量
'''
    1 定义在函数内部
    2 对外部作用域有引用(如果使用外部的可变类型,则直接使用;
        如果是不可变类型,需要使用nonlocal)
    
    例如:
    def add():
        a = 10
        def inner():
            nonlocal a
            a += 1
            print('闭包内部的值是:', a)  # 11
        inner()
        print('闭包外部的值是:', a)  # 11
    
    add()
'''

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方法实现

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方式实现


# 产生类这个对象的类,称之为元类
# 类中的 __call__什么时候回触发?对象()会触发
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):
        self.name = name


obj1 = Foo('name')
obj2 = Foo('name')
print(obj1.name)
print(obj1 is obj2)  # True

# __init__ 和 __new__ 区别是什么?
# 1 类()--->触发类中的__init__---->对象已经创建出来了,不能拦截住,做成单例了
# 2 类()----》触发类中的__new__----》真正的创建对象,判断之前有没有创建过,如果创建过,直接返回
# 3元类---》类()--->触发元类的__call__---》判断之前有没有创建过,如果有,直接返回

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 单例模式是一软件设计模式,其目的是保证一个只有一个实例,并提供一个全局访问点来访问这个实例。 在 Python ,可以使用装饰器实现单例模式装饰器是一特殊的装饰器,它可以在定义使用,用于修改的行为。 下面是使用装饰器实现单例模式的示例代码: ``` def singleton(cls): instance = None def wrapper(*args, **kwargs): nonlocal instance if instance is None: instance = cls(*args, **kwargs) return instance return wrapper @singleton class MyClass: pass ``` 在上面的代码,`singleton` 是一个装饰器,它接受一个作为参数,并返回一个内部函数 `wrapper`。`wrapper` 函数检查是否已经创建了的实例,如果没有,就创建一个新的实例,并将其保存在 `instance` 变量。如果已经创建了实例,就直接返回该实例。 使用装饰器实现单例模式时,可以使用 `nonlocal` 声明来修改内部函数的局部变量,这样就可以在多次调用 `wrapper` 函数时保存的实例。 使用装饰器实现单例模式后,就可以像调用普通一样调用单 ### 回答2: Python单例模式可以通过使用装饰器实现装饰器可以在原始上添加额外的功能,比如只实例化一个对象。 下面是一个使用装饰器实现Python单例模式的例子: ```python def singleton(cls): instances = {} def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper @singleton class MyClass: def __init__(self, x): self.x = x # 测试 obj1 = MyClass(10) obj2 = MyClass(20) # obj1 和 obj2指向同一个对象 print(obj1.x) # 输出 10 print(obj2.x) # 输出 10 print(obj1 is obj2) # 输出 True ``` 在这个例子,我们定义了一个名为singleton的装饰器函数。singleton函数接受一个作为参数,并返回一个新的封装函数wrapper。wrapper函数在被调用时会首先检查是否已经存在该的实例,如果不存在则创建一个新的实例并保存在字典instances,然后返回该实例。这样,每次创建新的对象时都会先检查是否已经有了同样的实例,如果有则返回之前的实例,实现单例模式。 我们的示例,我们定义了一个名为MyClass的,并在其上应用了singleton装饰器。这样,无论我们创建多少个MyClass的实例,它们都会指向同一个对象,因为只有第一次创建时实际上调用了MyClass的构造函数,后续创建都直接返回了之前的实例。 使用装饰器实现Python单例模式可以简化代码,并且保证了只有一个实例存在。这对于需要限制实例数量的场景非常有用。 ### 回答3: Python单例模式是一设计模式,用于确保一个只有一个实例,并提供一个全局访问点。 使用装饰器实现Python单例模式是一常见的方法装饰器是一个接受作为参数并返回修改后的的函数。 下面是一个使用装饰器实现Python单例模式的例子: ```python def singleton(cls): instances = {} def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper @singleton class MyClass: def __init__(self, name): self.name = name def say_hello(self): print("Hello, I am", self.name) # 创建实例 obj1 = MyClass("Object 1") obj2 = MyClass("Object 2") # 打印实例的名称 print(obj1.name) # Output: Object 1 print(obj2.name) # Output: Object 1 # 调用实例的方法 obj1.say_hello() # Output: Hello, I am Object 1 obj2.say_hello() # Output: Hello, I am Object 1 ``` 在上述例子,`singleton` 是一个装饰器函数。当我们在 `MyClass` 使用 `@singleton` 时,`singleton(MyClass)` 被调用并返回一个新的 `wrapper`。在这个新的 `wrapper` ,我们使用 `instances` 字典来存储已经创建的实例。在 `wrapper` 的构造函数,我们首先检查 `cls` 是否已经在 `instances` ,如果没有,则创建一个新的实例并将其添加到 `instances` 。最后,我们返回 `instances[cls]`,即返回已经创建的实例。 通过使用装饰器实现Python单例模式,我们可以确保在程序运行时只有一个实例存在,并且可以通过任何地方访问该实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值