我的装饰单身人士不起作用

时间:2017-10-10 11:57:20

标签: python singleton

我有一个singleton.py,其代码如下:

from functools import wraps

def singleton(cls):
    instances = {}

    @wraps(cls)
    def getinstance(*args, **kw):
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]
    return getinstance

@singleton
class OTConn():
    def __init__(self):
        self.conn = None

我有一个test01.py:

from app04 import singleton

ot_conn = singleton.OTConn()

ot_conn.conn = "a"

test02.py

import singleton

ot_conn = singleton.OTConn()

print (ot_conn.conn)  # there print: None

我在一个过程中运行test01.pytest02.py,但ot_conn.conn打印None

修改

我尝试将代码更改为:

@singleton
    class OTConn():
        conn = None
        def __init__(self):
            pass

还是不行。有些朋友可以帮我解决单身人士的装饰方法吗?

修改-2

请参阅此singleton method

装饰者方法与我的一样。

1 个答案:

答案 0 :(得分:1)

您似乎还不了解如何使用singleton装饰器。您错误地假设您使用singleton装饰的班级成为singleton属性。它没有。

这是一个如何工作的例子。请注意,我稍微修改了singleton的定义以删除一些错误。它只适用于Python 3.如果你需要在Python 3中使用这个装饰器,那么必须放回一些装置。

from functools import wraps

def singleton(cls):
    instance = None
    @wraps(cls)
    def getinstance(*args, **kwds):
        nonlocal instance
        if instance is None:
            instance = cls(*args, **kwds)
        return instance
    return getinstance

# Check that it works ... first use the decorator on a class definition
@singleton
class Foo:
    pass

# Now instantiate the class twice ...
a = Foo()
b = Foo()

# ... and verify that we have only one instance.
assert a is b

Python的is运算符验证对象标识。 assert a is b确认ab是同一个实例。

以下是如何验证它的工作方式类似于您在测试代码中尝试的更多内容:

# Showing how it works with your example
@singleton
class OTConn:
    # Your class variable `conn` and constructor were completely
    # irrelevant, so I leave them out
    pass

ot_conn_a = OTConn()
ot_conn_a.conn = 'a'

ot_conn_b = OTConn()
assert ot_conn_b.conn == 'a'

您的代码与我的代码之间最重要的区别是singleton.OTConn在我的任何地方都没有出现。它不可能工作! (除非有一些你没有向我们展示的代码,否则它会起作用。)

逐步说明如何正确观察singleton

您报告的行为以及您继续拒绝描述您认为您在一个过程中执行此代码的确切方式会给您留下非常强烈的印象,即您正在单独执行此操作流程。正如许多人所指出的那样,在这种情况下,你的单身类不可能正常工作

在这里,我将逐步介绍如何观察singleton在多个模块中正常工作,但只需一个进程

步骤1:创建一个目录(文件夹),您将在其中创建以下python源文件。

第2步:在您在步骤1中创建的目录中创建一个名为singleton.py的文件,其中包含以下代码:

def singleton(cls):
    instance = None
    @wraps(cls)
    def getinstance(*args, **kwds):
        nonlocal instance
        if instance is None:
            instance = cls(*args, **kwds)
        return instance
    return getinstance

第3步:在同一目录中创建一个名为theclass.py的文件,其中包含代码

from singleton import singleton

@singleton
class TheClass:

    def __init__(self):
        self.conn = None

步骤4:再次,在同一目录中创建一个名为client1.py的文件,其中包含

from theclass import TheClass

instance = TheClass()
print("In client1.py instance.conn =", instance.conn)
instance.conn = 'XXXX'
print("In client1.py instance.conn =", instance.conn)

步骤5:...以及包含

的名为client2.py的文件
from theclass import TheClass

instance = TheClass()
print("In client2.py instance.conn =", instance.conn)

步骤6:您需要的最后一个文件应该被称为main.py并包含

from client1 import instance as i1
from client2 import instance as i2

print("In main.py i1.conn =", i1.conn)
print("In main.py i2.conn =", i2.conn)

i2.conn = 'YYY'

print("In main.py i1.conn =", i1.conn)
print("In main.py i2.conn =", i2.conn)

第7步:执行main.py

步骤8:观察输出

In client1.py instance.conn = None
In client1.py instance.conn = XXXX
In client2.py instance.conn = XXXX
In main.py i1.conn = XXXX
In main.py i2.conn = XXXX
In main.py i1.conn = YYY
In main.py i2.conn = YYY

从输出中可以看出

  • TheClass在两个单独的模块中实例化。
  • 实例的conn属性以None
  • 开头
  • 将此属性的值设置为'XXXX'会将其设置为两个实例。
  • 将此属性的值设置为'YYY',这次使用其他实例,再次更改两个实例。

不可避免的结论是singleton的效果与宣传的一样。但这至关重要依赖于两个实例在同一过程中