zoukankan      html  css  js  c++  java
  • python中的单例模式

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

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

    在 Python 中,我们可以用多种方法来实现单例模式:

    • 使用模块
    • 使用 __new__
    • 使用装饰器(decorator)
    • 使用元类(metaclass)

    一、模块:

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

    # mysingleton.py
    class My_Singleton(object):
        def foo(self):
            pass
     
    my_singleton = My_Singleton()

    使用:

    from mysingleton import my_singleton
     
    my_singleton.foo()

    二、使用 __new__

    __new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。

    class Singleton(object):
        _instance = None
        def __new__(cls, *args, **kw):
            if not cls._instance:
                cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  
            return cls._instance  
     
    class MyClass(Singleton):  
        a = 1



    class Singleton(object):
    
    
        def __new__(cls):
    
    
            # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
    
    
            if not hasattr(cls, 'instance'):
    
    
                cls.instance = super(Singleton, cls).__new__(cls)
    
    
            return cls.instance
    
    
     
    obj1 = Singleton()
    
    
    obj2 = Singleton()
    
    
     
    obj1.attr1 = 'value1'
    
    
    print obj1.attr1, obj2.attr1
    
    
    print obj1 is obj2
    
    

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

    三、使用装饰器

    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

    注:functools.wraps 则可以将原函数对象的指定属性复制给包装函数对象, 默认有 __module____name____doc__,或者通过参数选择

    #不加wraps
    
    #coding=utf-8  
    # -*- coding=utf-8 -*-   
    from functools import wraps     
    def my_decorator(func):  
        def wrapper(*args, **kwargs):  
            '''''decorator'''  
            print('Calling decorated function...')  
            return func(*args, **kwargs)  
        return wrapper    
     
    @my_decorator   
    def example():  
        """Docstring"""   
        print('Called example function')  
    print(example.__name__, example.__doc__)  
    
    
    #结果:('wrapper', 'decorator')
    [Finished in 0.2s]
    
    
    #加wraps
    #coding=utf-8  
    # -*- coding=utf-8 -*-   
    from functools import wraps     
    def my_decorator(func):  
        @wraps(func)  
        def wrapper(*args, **kwargs):  
            '''''decorator'''  
            print('Calling decorated function...')  
            return func(*args, **kwargs)  
        return wrapper    
     
    @my_decorator   
    def example():  
        """Docstring"""   
        print('Called example function')  
    print(example.__name__, example.__doc__)  
    
    
    执行结果:
    ('example', 'Docstring')
    [Finished in 0.5s]
    functionstools.wraps

    四、使用 metaclass

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

    • 拦截类的创建
    • 修改类的定义
    • 返回修改后的类
    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
  • 相关阅读:
    URAL 2067 Friends and Berries (推理,数学)
    URAL 2070 Interesting Numbers (找规律)
    URAL 2073 Log Files (模拟)
    URAL 2069 Hard Rock (最短路)
    URAL 2068 Game of Nuts (博弈)
    URAL 2066 Simple Expression (水题,暴力)
    URAL 2065 Different Sums (找规律)
    UVa 1640 The Counting Problem (数学,区间计数)
    UVa 1630 Folding (区间DP)
    UVa 1629 Cake slicing (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/mona524/p/7716353.html
Copyright © 2011-2022 走看看