2

我在这里遇到了这个单例实现:http: //blog.amir.rachum.com/post/21850841339/implementing-the-singleton-pattern-in-python在第一个回复中。

def singleton(cls):
    return cls()

@singleton
class Foo(object):
    def bar(self):
        pass

if __name__ == '__main__':

    print id(Foo)
    print id(Foo) 

但我不明白内部工作原理,装饰器返回一个类实例,但为什么每次都是同一个实例?

4

2 回答 2

6

您可以将该代码重写为

class Foo(object):
    pass

Foo = singleton(Foo)
# which is
Foo = Foo()

所以这里类的名称被它的一个实例所取代。在我看来有点俗气,特别是因为您仍然可以通过使用创建同一类的新对象,Foo.__class__并且您正在弄乱命名模式。

于 2013-01-15T11:04:19.277 回答
1

单例通过保持内部状态来做到这一点。这里的状态可能是该类的一个实例。装饰器可以是任意的。

看看这个:

http://hairysun.com/downloads/DecoratorHandout.pdf

class Decorator(object):
    # in __init__ set up state
    def __call__(self, function):
        @functools.wraps(function)
        def wrapper(*args, **kw): # 1.
            print "before func"
            result = function(*args, **kw) # 2.
            print "after func"
            return result
        return wrapper # 3.

>>> decorator2 = Decorator()
>>> @decorator2
... def nothing(): pass

装饰器本质上是一个函数

  1. 定义一个函数
  2. 调用你传入的函数
  3. 返回稍后调用的新“包装”函数

周围的类(这里:装饰器)可以做这样的事情:

class Singleton(object):
     def __init__(self):
        self.instance = None

     def __call__(self, function):
         @functools.wraps(function)
         def wrapper(*args, **kw):
             if self.instance is None:
                self.instance = function(*args, **kw)
             return self.instance
         return wrapper

我没有运行代码,但我认为这通常是它的工作方式。如果没有可用的实例,则创建一个。如果一个可用,不要创建一个新的 - 而是返回一个旧的。在生产中使用它之前,可能需要检查可调用对象的其他属性。

于 2013-01-15T11:11:43.353 回答