我正在创建一个包含与服务器的套接字通信的Python应用程序。我想要一个可以在整个应用程序中使用的模块(其他几个模块)。目前我的模块看起来像这样:
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,因此我很想知道这类问题的最佳实践是什么?
答案 0 :(得分:4)
以下是在Python中使用单例的三种方法。
使用metaclass
和decorator
来达到目标。
使用__new__
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
使用__metaclass__
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
。
答案 1 :(得分:0)
单身人士存在争议,因为他们经常被用来作为结束全球变量的一种方式。这就是为什么有些人主张避免他们的原因。 Globals使测试更加困难,它们限制了访问控制,并且经常导致变量之间的强耦合。 (有关为什么全局变量通常是不好的做法的详细信息,请参阅http://wiki.c2.com/?GlobalVariablesAreBad)
在您的特定场景中,使用单例最有可能是合适的,因为您只是试图多次初始化SocketCommunication
(有充分理由),而不是尝试将其用作全局状态的容器
有关单身人士的一些讨论,请参阅Are Singletons really that bad?和What is so bad about singletons?。