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、挖坑
相关知识点:元类的使用之后研究