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
被返回。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)
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、挖坑
相關知識點:元類的使用之後研究