Python 實現單例模式的一些思考

1、問題:Python中如何實現單例模式html

  單例模式指一個類只能實例化一個對象。python

2、解決方案:函數

 

  全部資料參考於:學習

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

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

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

  1. 模塊對象

  永遠只有一次,這讓我下意識想到Python 的模塊,由於學習的時候就知道,屢次模塊導入是無效的,都至關於導入一次,由於模塊的導入十分消耗資源,如果重複導入那麼過低效了。blog

  所以能夠利用 導入模塊中的實例來實現這一目標。資源

  

#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

 

 

3、挖坑

相關知識點:元類的使用之後研究

相關文章
相關標籤/搜索