zoukankan      html  css  js  c++  java
  • Python 实现单例模式的一些思考

    一、问题:Python中如何实现单例模式

      单例模式指一个类只能实例化一个对象。

    二、解决方案:

      所有资料参考于:

    http://python.jobbole.com/87294/

    https://www.jianshu.com/p/f63ad9d550f1

    https://www.cnblogs.com/tkqasn/p/6524879.html

      1. 模块

      永远只有一次,这让我下意识想到Python 的模块,因为学习的时候就知道,多次模块导入是无效的,都相当于导入一次,因为模块的导入十分消耗资源,若是重复导入那么太低效了。

      因此可以利用 导入模块中的实例来实现这一目标。

      

    #singleton.py
    class SingleTon:
        def demo(self):
            print('hello world')
    singleton = SingleTon()
    
    #test.py
    from singleton import singleton
    singleton.demo()

      2. __new__方法

      这里涉及到类实例化过程,我想,要想做到永远实例化一个对象,换句话说只要这个类实例化后就不再实例化,那么我们必须在Python原有实例化过程中“做点手脚”

      那必要的就得现搞清楚实例化的具体过程。

      首先:Foo类的类型是type,Foo 类 也是一个对象,实例化加括号即调用 __call__方法,而type 就是 Python 内置的元类,通过type类生成Foo类,

      

    class Foo:
        def __init__(self):
            print('hello world')
    item = Foo()
    
    print(type(Foo),type(item))
    #<class 'type'> <class '__main__.Foo'>

      然后

    • Foo(*args, **kwargs)等价于Foo.__call__(*args, **kwargs)
    • 既然Foo是一个type的实例,Foo.__call__(*args, **kwargs)实际调用的是type.__call__(Foo, *args, **kwargs)
    • type.__call__(Foo, *args, **kwargs)调用type.__new__(Foo, *args, **kwargs),然后返回一个对象。
    • obj随后通过调用obj.__init__(*args, **kwargs)被初始化。
    • obj被返回。
    可见,__new__() 方法是创建对象,__init__() 是初始化,若要解决我们的问题,应该在 前者下功夫,


    class Foo:
        _instance = None
    
        def __new__(cls, *args, **kwargs):
            if cls._instance is None:
                cls._instance = super().__new__(cls,*args,**kwargs)
            return cls._instance
    
    
    item = Foo()
    item1 = Foo()
    print(item is item1)

      3. 装饰器

      使用装饰器应该也很方便,

    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

      wraps 函数 可以保证传入的类的属性不变,

      4. 元类(metaclass)

    str是用来创建字符串对象的类,而int是用来创建整数对象的类,type 是type就是创建类对象的类,元类在API的定义中会有很大用处,具体内容在https://www.cnblogs.com/tkqasn/p/6524879.html讲得很清楚
    Django的ORM 就是大量使用元类,有空研究一下。
    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

    三、挖坑

    相关知识点:元类的使用以后研究

  • 相关阅读:
    周总结
    周总结
    周总结
    读后感
    周总结
    周总结
    周总结
    第一周总结
    大学生失物招领平台使用体验
    快速乘法+快速幂
  • 原文地址:https://www.cnblogs.com/xinghuaikang/p/8489217.html
Copyright © 2011-2022 走看看