单例对象与装饰器 [英] singleton objects with decorators
问题描述
我一直在研究创建单例对象的方法。使用Python2.3我
通常使用模块级变量和工厂函数来实现
单例对象。
随着Python2.4我正在研究装饰器。 PEP 318中的示例
http:// www .python.org / peps / pep-0318.html#examples
不工作 - AFAIK因为:
- 你不能装饰类定义(为什么它被遗漏?)
- __init__必须返回无
但是,你可以使用装饰器:
def singleton(f):
instances = {}
def new_f(* args,** kwargs):
if(f不在实例中):
实例[f] = f(* args,** kwargs)
返回实例[f]
new_f。 func_name = f.func_name
new_f.func_doc = f.func_doc
返回new_f
,其中一个类覆盖了__new__的方法新式课程:
class Foobar(对象):
def __init __(自我):
print self
@singleton
def __new __(自我):
返回对象.__ new __(Foobar)
是这特别难看还是坏?
感谢您的评论,
Ciao
Uwe
Uwe Mayer写道:
我一直在研究创建单例对象的方法。使用Python2.3我通常使用模块级变量和工厂函数来实现单件对象。
使用Python2.4我正在寻找装饰器。 PEP 318中的示例
http:// www .python.org / peps / pep-0318.html#examples
不工作 - AFAIK因为:
- 你不能装饰类定义(为什么它还剩下出来?)
- __ init__必须返回无
但是,你可以使用装饰器:
def singleton(f):
instances = {}
def new_f(* args,** kwargs):
if(f不在实例中):
实例[f] = f(* args,** kwargs)
返回实例[f]
new_f.func_name = f.func_name
new_f.func_doc = f.func_doc
返回new_f
用一个覆盖新的__new__方法的类式班:
班Foobar(对象):
def __init __(个体经营):
打印自我
@singleton
def __new__ (个体经营):
返回物体.__新__(Foobar)
这是特别难看的还是坏?
似乎有点混乱。为什么你不能只使用类似的东西:
class Singleton(object):
def __new __(cls,* args,** kwargs):
尝试:
返回cls .__ instance__
除了AttributeError:
instance = cls .__ instance__ = super(Singleton ,cls).__ new __(
cls,* args,** kwargs)
返回实例
class Foobar(Singleton) :
def __init __(个体经营):
打印自我
?
STeVe
2005年4月11日星期一17:26:09 +0200,Uwe Mayer< me ***** @ hadiko.de>写道:
我一直在研究创建单例对象的方法。使用Python2.3我通常使用模块级变量和工厂函数来实现单件对象。
使用Python2.4我正在寻找装饰器。 PEP 318中的示例
http:// www .python.org / peps / pep-0318.html#examples
不工作 - AFAIK因为:
- 你不能装饰类定义(为什么它还剩下出来?)
- __ init__必须返回无
但是,你可以使用装饰器:
def singleton(f):
instances = {}
def new_f(* args,** kwargs):
if(f不在实例中):
实例[f] = f(* args,** kwargs)
返回实例[f]
new_f.func_name = f.func_name
new_f.func_doc = f.func_doc
返回new_f
用一个覆盖新的__new__方法的类式班:
班Foobar(对象):
def __init __(个体经营):
打印自我
@singleton
def __new__ (自我):
返回对象.__新__(Foobar)
这特别难看还是坏?
请求评论,
我想到了一种不同的方法。这里的单例函数
为类的初始实例接受参数,并实例化它,
然后修改类的__new__和__init__以返回初始
实例并防止进一步初始化。
直接使用,因为正常的函数装饰器可以(即,fun = deco(fun)
或fun = deco(args)(有趣)),单例工作(不计算错误;-)按原样。
要作为装饰器调用它需要使用中间件的技巧解决方法
变通方装饰器和虚拟功能定义与要装饰的
类同义(为此预先存在)。
顺便说一下,这不同于类装饰者作为糖类的元类,
(我之前建议),因为它需要一个类参数vs参数
对于元类__new__等
我添加了一个单独的装饰器,当你不想立刻想要
时y第一个initiazization参数,但是希望第一个实例
在以后发生时成为单例实例。
所以这里有一些hacks to玩:
----< singleton.py> --------------------------------------------- -
def singleton(* args,** kw):
""" decorator cacheing singleton instance""
def singdeco(cls):
断言isinstance(cls,type)
inst = cls(* args,** kw)
cls .__ new__ = staticmethod(lambda * a,** kw:inst)
cls .__ init__ = staticmethod(lambda * a,** kw:None)#no re-init
返回cls
返回singdeco
导入系统
def workaround(f):
cls = sys._getframe(1).f_locals.get(f.func_name)
如果cls为None:
cls = sys._getframe(1).f_globals .get(f.func_name)
返回cls
def singularize(cls):
""" decorator设置单身制作捕鼠器""
oldnew = cls .__ new__
def __new __(cls,* args,** kw):
inst = oldnew(cls)
inst .__ init __(* args,** kw)
cls .__ new__ = staticmethod(lambda * a,** kw:inst)
cls .__ init__ = staticmethod(lambda * a,** kw:None)
return inst
cls .__ new__ = staticmethod(__ new__)
return cls
def test():
类Foobar(物件):传递
Foobar = singleton()(Foobar)
打印Foobar
打印[Foobar( )for x in xrange(2)]
class Boobar(对象):
def __init __(self,v):
打印自己,v
self.v = v
@singleton(123)
@workaround
def Boobar():传递#dummy用于解决方法名称
打印Boobar
打印[Boobar(x)for x in xrange(2)]
打印[Boobar(x).v for x in xrange(2)]
class Gee(对象):
def __init__ (个体经营):打印''啧啧:'',自我
Gee = singularize(啧啧)
打印Gee
打印[Gee()for x in xrange(2)]
class Haw(对象):
def __init __(self,* args,** kw):
self.args = args
self.kw = kw
>
Haw = singularize(Haw)
haw = Haw(1,2L,3.5,s =''string'',more =''example'')
print vars(haw)
print vars(Haw(111,a =''222''))
print [Haw(),Haw()]
打印[Haw()。args [i] for x in xrange(len(Haw()。args))]
print [Haw()。kw [' 's''],Haw()。kw [''more'']]
如果__name__ ==''__ main__'':
test()
-------------------------------------------- -----------------------
无保证,介意;-)
输出,显示单个实例,不重复初始化:
< class''__ main __。Foobar''>
[< __ main __。Foobar对象at 0x02F03BEC>,< __ main __。位于0x02F03BEC的Foobar对象>]
< __ main __。位于0x02F03DCC的Boobar对象> 123
< class''__ main __。Boobar''>
[< __ main __。在0x02F03DCC处的Boobar对象>,< __ main __。在0x02F03DCC处的Boobar对象>]
[123,123]
< class''__ main __。Gee''>
Gee:< __ main __。Gee对象at 0x02F03E8C>
[< __ main __。位于0x02F03E8C的Gee对象>,< __ main __。位于0x02F03E8C的Gee对象>]
{''args'':( 1,2L ,3.5),''kw'':{''s'':''string'',''more'':''example''}}
{''args'' :(1,2L,3.5),''kw'':{''s'':''string'',''more'':''example''}}
[ < __ main __。Haw对象位于0x02F03F0C>,< __ main __。Haw对象位于0x02F03F0C>]
[1,2L,3.5]
[''string'', ''示例'']
问候,
Bengt Richter
Uwe Mayer写道:< blockquote class =post_quotes>我一直在调查创建单件对象的方法。
我从来没想过或者需要一个单件对象让我感到震惊。
你介意分享吗?你的用例?我很好奇。
谢谢,
STeVe
Hi,
I''ve been looking into ways of creating singleton objects. With Python2.3 I
usually used a module-level variable and a factory function to implement
singleton objects.
With Python2.4 I was looking into decorators. The examples from PEP 318
http://www.python.org/peps/pep-0318.html#examples
don''t work - AFAIK because:
- you cannot decorate class definitions (why was it left out?)
- __init__ must return None
However, you can use the decorator:
def singleton(f):
instances = {}
def new_f(*args, **kwargs):
if (f not in instances):
instances[f] = f(*args, **kwargs)
return instances[f]
new_f.func_name = f.func_name
new_f.func_doc = f.func_doc
return new_f
with a class that overwrites the __new__ methof of new-style classes:
class Foobar(object):
def __init__(self):
print self
@singleton
def __new__(self):
return object.__new__(Foobar)
Is this particularly ugly or bad?
Thanks for comments,
Ciao
Uwe
Uwe Mayer wrote:Hi,
I''ve been looking into ways of creating singleton objects. With Python2.3 I
usually used a module-level variable and a factory function to implement
singleton objects.
With Python2.4 I was looking into decorators. The examples from PEP 318
http://www.python.org/peps/pep-0318.html#examples
don''t work - AFAIK because:
- you cannot decorate class definitions (why was it left out?)
- __init__ must return None
However, you can use the decorator:
def singleton(f):
instances = {}
def new_f(*args, **kwargs):
if (f not in instances):
instances[f] = f(*args, **kwargs)
return instances[f]
new_f.func_name = f.func_name
new_f.func_doc = f.func_doc
return new_f
with a class that overwrites the __new__ methof of new-style classes:
class Foobar(object):
def __init__(self):
print self
@singleton
def __new__(self):
return object.__new__(Foobar)
Is this particularly ugly or bad?
Seems a little confoluted. Why can''t you just use something like:
class Singleton(object):
def __new__(cls, *args, **kwargs):
try:
return cls.__instance__
except AttributeError:
instance = cls.__instance__ = super(Singleton, cls).__new__(
cls, *args, **kwargs)
return instance
class Foobar(Singleton):
def __init__(self):
print self
?
STeVe
On Mon, 11 Apr 2005 17:26:09 +0200, Uwe Mayer <me*****@hadiko.de> wrote:
Hi,
I''ve been looking into ways of creating singleton objects. With Python2.3 I
usually used a module-level variable and a factory function to implement
singleton objects.
With Python2.4 I was looking into decorators. The examples from PEP 318
http://www.python.org/peps/pep-0318.html#examples
don''t work - AFAIK because:
- you cannot decorate class definitions (why was it left out?)
- __init__ must return None
However, you can use the decorator:
def singleton(f):
instances = {}
def new_f(*args, **kwargs):
if (f not in instances):
instances[f] = f(*args, **kwargs)
return instances[f]
new_f.func_name = f.func_name
new_f.func_doc = f.func_doc
return new_f
with a class that overwrites the __new__ methof of new-style classes:
class Foobar(object):
def __init__(self):
print self
@singleton
def __new__(self):
return object.__new__(Foobar)
Is this particularly ugly or bad?
Thanks for comments,
I thought of a different approach. The singleton function here
takes arguments for the initial instance of a class, and instantiates it,
and then modifies the class''s __new__ and __init__ to return the initial
instance and prevent further initialization.
Used directly, as normal function decorators can be (i.e., fun = deco(fun)
or fun = deco(args)(fun)), singleton works (not counting bugs ;-) as is.
To invoke it as decorator demands a trick workaround using an intermediate
workaround decorator and a dummy funcion definition synonymous with the
class to be decorated (which mus pre-exist for this).
BTW, this is different from the class-decorator-as-sugar-for-metaclass,
(which I suggested previously) since it take one class argument vs arguments
for the metaclass __new__ etc.
I added a singularize decorator for when you don''t immediately want to
specify the first initiazization parameters, but want the first instance
to to become the singleton instance whenever that happens later.
So here''s some hacks to play with:
----< singleton.py >-----------------------------------------------
def singleton(*args, **kw):
"""decorator cacheing singleton instance immediately"""
def singdeco(cls):
assert isinstance(cls, type)
inst = cls(*args, **kw)
cls.__new__ = staticmethod(lambda *a, **kw: inst)
cls.__init__ = staticmethod(lambda *a, **kw: None) # no re-init
return cls
return singdeco
import sys
def workaround(f):
cls = sys._getframe(1).f_locals.get(f.func_name)
if cls is None:
cls = sys._getframe(1).f_globals.get(f.func_name)
return cls
def singularize(cls):
"""decorator setting singleton-making mousetrap"""
oldnew = cls.__new__
def __new__(cls, *args, **kw):
inst = oldnew(cls)
inst.__init__(*args, **kw)
cls.__new__ = staticmethod(lambda *a,**kw: inst)
cls.__init__ = staticmethod(lambda *a, **kw: None)
return inst
cls.__new__ = staticmethod(__new__)
return cls
def test():
class Foobar(object): pass
Foobar = singleton()(Foobar)
print Foobar
print [Foobar() for x in xrange(2)]
class Boobar(object):
def __init__(self, v):
print self, v
self.v = v
@singleton(123)
@workaround
def Boobar(): pass # dummy used by workaround for name
print Boobar
print [Boobar(x) for x in xrange(2)]
print [Boobar(x).v for x in xrange(2)]
class Gee(object):
def __init__(self): print ''Gee:'', self
Gee = singularize(Gee)
print Gee
print [Gee() for x in xrange(2)]
class Haw(object):
def __init__(self, *args, **kw):
self.args = args
self.kw =kw
Haw = singularize(Haw)
haw = Haw(1,2L, 3.5, s=''string'', more=''example'')
print vars(haw)
print vars(Haw(111, a=''222''))
print [Haw(), Haw()]
print [Haw().args[i] for i in xrange(len(Haw().args))]
print [Haw().kw[''s''], Haw().kw[''more'']]
if __name__ == ''__main__'':
test()
-------------------------------------------------------------------
No guarantees, mind ;-)
Output, showing single instances and no repeat initialization:
<class ''__main__.Foobar''>
[<__main__.Foobar object at 0x02F03BEC>, <__main__.Foobar object at 0x02F03BEC>]
<__main__.Boobar object at 0x02F03DCC> 123
<class ''__main__.Boobar''>
[<__main__.Boobar object at 0x02F03DCC>, <__main__.Boobar object at 0x02F03DCC>]
[123, 123]
<class ''__main__.Gee''>
Gee: <__main__.Gee object at 0x02F03E8C>
[<__main__.Gee object at 0x02F03E8C>, <__main__.Gee object at 0x02F03E8C>]
{''args'': (1, 2L, 3.5), ''kw'': {''s'': ''string'', ''more'': ''example''}}
{''args'': (1, 2L, 3.5), ''kw'': {''s'': ''string'', ''more'': ''example''}}
[<__main__.Haw object at 0x02F03F0C>, <__main__.Haw object at 0x02F03F0C>]
[1, 2L, 3.5]
[''string'', ''example'']
Regards,
Bengt Richter
Uwe Mayer wrote:I''ve been looking into ways of creating singleton objects.
It strikes me that I''ve never wanted or needed a singleton object.
Would you mind sharing your use case? I''m just curious.
Thanks,
STeVe
这篇关于单例对象与装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!