我有一个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.py
和test02.py
,但ot_conn.conn
打印None
。
修改
我尝试将代码更改为:
@singleton
class OTConn():
conn = None
def __init__(self):
pass
还是不行。有些朋友可以帮我解决单身人士的装饰方法吗?
修改-2
请参阅此singleton method
装饰者方法与我的一样。
答案 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
确认a
和b
是同一个实例。
以下是如何验证它的工作方式类似于您在测试代码中尝试的更多内容:
# 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
的效果与宣传的一样。但这至关重要依赖于两个实例在同一过程中 。