python单例模式

python单例模式

一. 什么是单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。

二. 如何实现单例模式

在 Python 中,我们可以用多种方法来实现单例模式:
使用模块
使用 new
使用装饰器(decorator)
使用元类(metaclass)

2.1 使用模块

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

1
2
3
4
5
6
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass

my_singleton = My_Singleton()

将上面的代码保存在文件 mysingleton.py 中,然后这样使用:

1
2
from mysingleton import my_singleton
my_singleton.foo()

2.2 使用new

new()在init()之前被调用,用于生成实例对象。利用这个方法和类的属性的特点可以实现设计模式的单例模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Singeton(object):
"""
单例模式
"""

def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
# orig = super(Singeton, cls)
cls._instance = super(Singeton, cls).__new__(cls, *args, **kwargs)
return cls._instance


class MyCLass(Singeton):
a = 1

one = MyCLass()
two = MyCLass()
print(one is two)
print(one == two)
print(id(one), id(two))

"""
输出:
True
True
4436793720 4436793720
"""

在上面的代码中,我们将类的实例和一个类变量 _instance 关联起来,如果 cls._instance 为 None 则创建实例,否则直接返回 cls._instance

2.3 共享属性

创建实例时把所有实例的dict指向同一个字典,这样它们具有相同的属性和方法.

1
2
3
4
5
6
7
8
9
10
11
class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob

class MyClass2(Borg):
a = 1

# 没明白该方式如何实现单例

2.4 装饰器方式

我们知道,装饰器(decorator)可以动态地修改一个类或函数的功能。这里,我们也可以使用装饰器来装饰某个类,使其只能生成一个实例,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from functools import wraps

def singleton(cls):
instances = {}

@wraps(cls)
def getinstance(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]

return getinstance


@singleton
class MyClass(object):
a = 1

one = MyClass()
two = MyClass()
print(one is two)
print(one == two)
print(id(one), id(two))

"""
True
True
4492352536 4492352536
"""

在上面,我们定义了一个装饰器singleton,它返回了一个内部函数 getinstance,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key,cls(*args, **kw)作为 value存到instances中,否则,直接返回 instances[cls]。

2.5 使用metaclass

元类(metaclass)可以控制类的创建过程,它主要做三件事:

  • 拦截类的创建
  • 修改类的定义
  • 返回修改后的类
    使用元类实现单例模式的代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
    if cls not in cls._instances:
    cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
    return cls._instances[cls]

    # Python2
    class MyClass(object):
    __metaclass__ = Singleton


    # Python3
    class MyClass(metaclass=Singleton):
    pass

本文标题:python单例模式

文章作者:shuke

发布时间:2020年04月23日 - 16:04

最后更新:2020年04月23日 - 16:04

原始链接:https://shuke163.github.io/2020/04/23/python%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------

本文标题:python单例模式

文章作者:shuke

发布时间:2020年04月23日 - 16:04

最后更新:2020年04月23日 - 16:04

原始链接:https://shuke163.github.io/2020/04/23/python%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%