Python实现单例模式
2017-05-25 11:06
127 查看
定义
An implementation of the singleton pattern must:ensure that only one instance of the singleton class ever exists; and
provide global access to that instance.
单例模式就是保证类在整个使用过程中有且只有一个实例.
Python原理
要想保证类的使用过程中有且只有一个实例, 就需要对Python中类的实例化, 以及实例化后的使用过程有所了解. 这个过程主要涉及到3个方法:__new__
__init__
__call__
这3个方法的调用过程是: 首先调用
__new__, 来生成新的实例; 其次, 调用
__init__对新实例进行相关设置; 最后, 如果类中实现了
__call__方法的话, 那么类的实例也是一个可调用对象, 调用实例时
instance()其实就是调用实例所属的类类的
__call__方法.
清楚了3个方法的调用时机, 再结合单例模式的定义就不难实现Python版本的单例模式了.
Python实现
Python中实现单例模式主要有一下几种方式:__call__
__new__
__call__
在python中一切都是对象, 类其实也是一个对象, 一个类是其元类(MetaClass)的实例(定义类的时候其实就会调用元类的__init__方法).
这样理解过来, 类的实例初始化实际上就是通过调用了类的元类的
__call__方法实现的.
# coding: utf-8 """ 代码摘在mininet源代码 """ class Singleton( type ): """Singleton pattern from Wikipedia See http://en.wikipedia.org/wiki/Singleton_Pattern Intended to be used as a __metaclass_ param, as shown for the class below.""" def __new__( cls, *args, **kw ): return super( Singleton, cls ).__new__( cls, *args, **kw ) def __init__( cls, name, bases, dict_ ): super( Singleton, cls ).__init__( name, bases, dict_ ) cls.instance = None def __call__( cls, *args, **kw ): if cls.instance is None: cls.instance = super( Singleton, cls ).__call__( *args, **kw ) return cls.instance class MininetLogger( Logger, object ): """Mininet-specific logger Enable each mininet .py file to with one import: from mininet.log import [lg, info, error] ...get a default logger that doesn't require one newline per logging call. Inherit from object to ensure that we have at least one new-style base class, and can then use the __metaclass__ directive, to prevent this error: TypeError: Error when calling the metaclass bases a new-style class can't have only classic bases If Python2.5/logging/__init__.py defined Filterer as a new-style class, via Filterer( object ): rather than Filterer, we wouldn't need this. Use singleton pattern to ensure only one logger is ever created.""" __metaclass__ = Singleton def __init__( self ): Logger.__init__( self, "mininet" ) # create console handler ch = StreamHandlerNoNewline() # create formatter formatter = logging.Formatter( LOGMSGFORMAT ) # add formatter to ch ch.setFormatter( formatter ) # add ch to lg self.addHandler( ch ) self.setLogLevel() def setLogLevel( self, levelname=None ): """Setup loglevel. Convenience function to support lowercase names. levelName: level name from LEVELS""" level = LOGLEVELDEFAULT if levelname is not None: if levelname not in LEVELS: raise Exception( 'unknown levelname seen in setLogLevel' ) else: level = LEVELS.get( levelname, level ) self.setLevel( level ) self.handlers[ 0 ].setLevel( level ) # pylint: disable=method-hidden # "An attribute inherited from mininet.log hide this method" (sic) # Not sure why this is occurring - this function definitely gets called. # See /usr/lib/python2.5/logging/__init__.py; modified from warning() def output( self, msg, *args, **kwargs ): """Log 'msg % args' with severity 'OUTPUT'. To pass exception information, use the keyword argument exc_info with a true value, e.g. logger.warning("Houston, we have a %s", "cli output", exc_info=1) """ if self.manager.disable >= OUTPUT: return if self.isEnabledFor( OUTPUT ): self._log( OUTPUT, msg, args, kwargs ) # pylint: enable=method-hidden
每次实例化MininetLogger时, 其实调用了Singleton的
__call__方法, 这个可以在Singleton和MininetLogger类中相关方法添加打印日志进行验证.
当然Singleton还有其他的定义方式:
# https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python 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]
但是这种方式在多个类(A, B)同时指向Singleton为
__metaclass__的话, 当实例化A后, 可以通过
B._instances看到到A的instance.
__new__
每次实例化一个类的新实例的时候其实会调用类的__new__方法, 这样就可以通过在类的
__new__方法中进行唯一实例的控制.
# https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if not isinstance(cls._instance, cls): cls._instance = object.__new__(cls, *args, **kwargs) return cls._instance class A(Singleton): pass id(A()) == id(A()) # True
总结
单例模式就是保证在整个程序使用过程中无论实例化(class())多少次, 在内存中只保存一个实例.在Python中通过利用
__new__和
__call__两个魔法函数就可以通过在类或者类的元类中定义这两个方法实现单例模式.
相关文章推荐
- 观察者模式 python实现
- 用Python的类变量实现单一模式
- Python单例模式的4种实现方法
- 设计模式八(原型模式,python语言实现)
- 设计模式六(建造者模式,采用python实现)
- python中实现Single模式
- 设计模式十二(组合模式,python语言实现)
- python:装饰模式的一个实现
- Python单例模式(元类实现)
- 设计模式十(适配器模式,python语言实现)
- Head First 设计模式——策略模式(Strategy Pattern)——Python实现
- Head First 设计模式—Python实现
- Head First 设计模式——装饰器(Decorator Pattern)——Python实现
- python实现C#中类似于AutoResetEvent类的阻塞模式
- 设计模式之策略模式(python实现)
- <读书笔记> Thinking in python (Python 设计模式) 1. Singlton的c++与python的实现
- Head First 设计模式——观察者模式(Observer Pattern)——Python实现(3)
- python 实现单例模式
- 设计模式二(策略模式,采用python实现)
- 设计模式十一(桥接模式,python 语言实现)