python工厂模式和单例模式_详解python单例模式与metaclass

单例模式的实现方式

将类实例绑定到类变量上

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 _clsnot 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, valuein dct.items()if not name.startswith('__'))

uppercase_attr= {name.upper(): valuefor name, valuein 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: 'Foo' () {'__module__':'__main__','__metaclass__': ,'__init__': }

init: 'Foo' () {'__module__':'__main__','__metaclass__': ,'__init__': }

call: ('a',)

init: <__main__.Fooobject at0x106fee990> ('a',) {}

call: ('b',)

init: <__main__.Fooobject at0x106feea50> ('b',) {}

元类的__init__和__new__只在创建类Foo调用了一次,而创建Foo的实例时,每次都会调用元类的__call__方法

以上就是本文的全部内容,对python单例模式与metaclass进行了描述,希望对大家的学习有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值