Python中类的单个实例
我正在创建一个Python应用程序,其中包括与服务器的套接字通信。我想有一个模块,可以在我的整个应用程序中使用(几个其他模块)。当前我的模块如下所示:Python中类的单个实例,python,class,sockets,singleton,instance,Python,Class,Sockets,Singleton,Instance,我正在创建一个Python应用程序,其中包括与服务器的套接字通信。我想有一个模块,可以在我的整个应用程序中使用(几个其他模块)。当前我的模块如下所示: class SocketCommunication: def __init__(self): self.socketIO = SocketIO(settings.ADDRESS, settings.PORT, Namespace) def emit(self, message, data): j
class SocketCommunication:
def __init__(self):
self.socketIO = SocketIO(settings.ADDRESS, settings.PORT, Namespace)
def emit(self, message, data):
json_data = json.dumps(data.__dict__)
self.socketIO.emit(message, json_data)
class Namespace(BaseNamespace):
def on_connect(self):
print '[Connected]'
def on_disconnect(self):
print "[Disconnected]"
当我在其他模块中使用此功能时,我会执行以下操作:
import SocketCommunication
self.sc = SocketCommunication()
问题是,每次我这样做时,都会创建一个新连接,该连接将显示为服务器上的新客户端,这是不可取的。
据我所知,在Python中应该避免使用单例,因此我很好奇对于这种类型的问题,什么是最佳实践 单例是有争议的,因为它们经常被用来包装全局变量。这就是为什么有些人主张回避。全局变量使测试更加困难,它们限制了访问控制,并且常常导致变量之间的强耦合。(请参阅了解有关为什么globals通常是不好的做法的更多详细信息) 在您的特定场景中,使用单例很可能是最合适的,因为您只是尝试停止多次初始化
SocketCommunication
(有充分的理由),而不是尝试将其用作全局状态的容器
有关单例的一些讨论,请参见和。以下是在Python中使用单例的三种方法。 使用
元类
和装饰器
达到目标
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
class MyClass(Singleton):
a = 1
one = MyClass()
two = MyClass()
two.a = 3
print one.a
#3
print id(one)
#29097904
print id(two)
#29097904
print one == two
#True
print one is two
#True
\uuuu元类
class Singleton2(type):
def __init__(cls, name, bases, dict):
super(Singleton2, cls).__init__(name, bases, dict)
cls._instance = None
def __call__(cls, *args, **kw):
if cls._instance is None:
cls._instance = super(Singleton2, cls).__call__(*args, **kw)
return cls._instance
class MyClass2(object):
__metaclass__ = Singleton2
one = MyClass2()
two = MyClass2()
two.a = 3
print one.a
#3
print id(one)
#31495472
print id(two)
#31495472
print one == two
#True
print one is two
#True
decorator
def singleton(cls, *args, **kw):
instances = {}
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return _singleton
@singleton
class MyClass3(object):
a = 1
def __init__(self, x=0):
self.x = x
one = MyClass3()
two = MyClass3()
two.a = 3
print one.a
#3
print id(one)
#29660784
print id(two)
#29660784
print one == two
#True
print one is two
#True
one.x = 1
print one.x
#1
print two.x
#1
我更喜欢使用
decorator
阅读有关博格设计模式的内容,以及将类转换为单例的简单方法。还有其他方法。我会将类本身作为一个单例使用。我从未遇到过这种方法的问题。您在其他模块中所说的导入SocketCommunication不起作用,因为SocketCommunication
是您的一个类的名称。它需要类似于my_module import SocketCommunication的,才能使下一行有效。这就是说,在定义类之后,可以在my_module.py
文件中添加SocketCommunication=SocketCommunication()
,从而有效地将类设置为单例。这样就很难创建更多的实例,因为类名将被自身的实例覆盖。谢谢您的回答。在这种特殊情况下,当我只需要类的单个实例时,单例是最好的解决方案。装饰参数*args
和**kwargs
应该是\u singleton
方法的输入,而不是singleton
类的输入,否?装饰器解决方案的另一个警告可能是,如果您有类变量,此单例将用函数替换该类,并且通过MyClass.class\u VAR
访问该变量的权限将丢失。