单例模式的实现方式
将类实例绑定到类变量上
1
2
3
4
5
6
7
|
class Singleton( object ):
_instance = None
def __new__( cls , * args):
if not isinstance ( cls ._instance, cls ):
cls ._instance = super (Singleton, cls ).__new__( cls , * args)
return cls ._instance
|
但是子类在继承后可以重写__new__以失去单例特性
1
2
3
4
|
class D(Singleton):
def __new__( cls , * args):
return super (D, cls ).__new__( cls , * args)
|
使用装饰器实现
1
2
3
4
5
6
7
8
9
10
11
12
|
def singleton(_cls):
inst = {}
def getinstance( * args, * * kwargs):
if _cls not in inst:
inst[_cls] = _cls( * args, * * kwargs)
return inst[_cls]
return getinstance
@singleton
class MyClass( object ):
pass
|
问题是这样装饰以后返回的不是类而是函数,当然你可以singleton里定义一个类来解决问题,但这样就显得很麻烦了
使用__metaclass__,这个方式最推荐
1
2
3
4
5
6
7
8
9
10
11
|
class Singleton( type ):
_inst = {}
def __call__( cls , * args, * * kwargs):
if cls not in cls ._inst:
cls ._inst[ cls ] = super (Singleton, cls ).__call__( * args)
return cls ._inst[ cls ]
class MyClass( object ):
__metaclass__ = Singleton
|
metaclass
元类就是用来创建类的东西,可以简单把元类称为“类工厂”,类是元类的实例。type就是Python的内建元类,type也是自己的元类,任何一个类
1
2
3
4
|
>>> type (MyClass)
type
>>> type ( type )
type
|
python在创建类MyClass的过程中,会在类的定义中寻找__metaclass__,如果存在则用其创建类MyClass,否则使用内建的type来创建类。对于类有继承的情况,如果当前类没有找到,会继续在父类中寻找__metaclass__,直到所有父类中都没有找到才使用type创建类。
如果模块里有__metaclass__的全局变量的话,其中的类都将以其为元类,亲自试了,没这个作用,无任何影响
查看type的定义,
type(object) -> the object's type
type(name, bases, dict) -> a new type
所以利用type定义一个类的元类,可以用函数返回一个上面第二种定义的对象,也可以继承type并重写其中的方法。
直接使用type生成的对象作为元类,函数作用是使属性变为大写
1
2
3
4
5
6
7
8
9
10
11
12
13
|
def update_(name, bases, dct):
attrs = ((name, value) for name, value in dct.items() if not name.startswith( '__' ))
uppercase_attr = {name.upper(): value for name, value in attrs}
return type (name, bases, uppercase_attr)
class Singleton( object ):
__metaclass__ = update_
abc = 2
d = Singleton()
print d.ABC
# 2
|
上一节中,单例模式元类实现用的是类继承方式,而对于第一种__new__的方式,本质上调用的是type.__new__,不过使用super能使继承更清晰一些并避免一些问题
这里简单说明一下,__new__是在__init__前调用的方法,会创建对象并返回,而__init__则是用传入的参数将对象初始化。看一下type中这两者以及__call__的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
def __init__( cls , what, bases = None , dict = None ): # known special case of type.__init__
"""
type(object) -> the object's type
type(name, bases, dict) -> a new type
# (copied from class doc)
"""
pass
@staticmethod # known case of __new__
def __new__(S, * more): # real signature unknown; restored from __doc__
""" T.__new__(S, ...) -> a new object with type S, a subtype of T """
pass
def __call__( self , * more): # real signature unknown; restored from __doc__
""" x.__call__(...) <==> x(...) """
pass
|
前面提到类相当于元类的实例化,再联系创建单例模式时使用的函数,用的是__call__,其实用三种magic method中任何一种都是可以的,来看一下使用元类时各方法的调用情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class Basic( type ):
def __new__( cls , name, bases, newattrs):
print "new: %r %r %r %r" % ( cls , name, bases, newattrs)
return super (Basic, cls ).__new__( cls , name, bases, newattrs)
def __call__( self , * args):
print "call: %r %r" % ( self , args)
return super (Basic, self ).__call__( * args)
def __init__( cls , name, bases, newattrs):
print "init: %r %r %r %r" % ( cls , name, bases, newattrs)
super (Basic, cls ).__init__(name, bases, dict )
class Foo:
__metaclass__ = Basic
def __init__( self , * args, * * kw):
print "init: %r %r %r" % ( self , args, kw)
a = Foo( 'a' )
b = Foo( 'b' )
|
结果
1
2
3
4
5
6
|
new: < class '__main__.Basic' > 'Foo' () { '__module__' : '__main__' , '__metaclass__' : < class '__main__.Basic' >, '__init__' : <function init at 0x106fd5320 >}
init: < class '__main__.Foo' > 'Foo' () { '__module__' : '__main__' , '__metaclass__' : < class '__main__.Basic' >, '__init__' : <function init at 0x106fd5320 >}
call: < class '__main__.Foo' > ( 'a' ,)
init: <__main__.Foo object at 0x106fee990 > ( 'a' ,) {}
call: < class '__main__.Foo' > ( 'b' ,)
init: <__main__.Foo object at 0x106feea50 > ( 'b' ,) {}
|
元类的__init__和__new__只在创建类Foo调用了一次,而创建Foo的实例时,每次都会调用元类的__call__方法
以上就是本文的全部内容,对python单例模式与metaclass进行了描述,希望对大家的学习有所帮助。