单例对象与装饰器 [英] singleton objects with decorators

查看:65
本文介绍了单例对象与装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我一直在研究创建单例对象的方法。使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆