Single instance of class in Python
我正在创建一个包含与服务器的套接字通信的python应用程序。我希望有一个模块可以在整个应用程序中使用(其他几个模块)。当前我的模块如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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]" |
当我在其他模块中使用它时,我会执行以下操作:
1 2 | import SocketCommunication self.sc = SocketCommunication() |
问题是每次我这样做时,都会创建一个新的连接,它将在服务器上显示为一个新的客户机,这是不可取的。据我所知,在Python中应该避免使用单例,因此我对这种类型的问题的最佳实践是什么感到好奇?
下面是在Python中使用singleton的三种方法。使用
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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 |
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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 |
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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 |
我喜欢用
单件是有争议的,因为它们经常被用来包装全局变量。这就是为什么有些人主张回避的原因。全局性使测试更加困难,它们限制了访问控制,并且常常导致变量之间的强耦合。(参见http://wiki.c2.com/?全球变量不利于更详细地解释为什么全球变量通常是不好的做法)
在您的特定场景中,使用单例是最合适的,因为您只是在尝试停止多次初始化
看到单身汉真的那么糟糕吗?单身汉有什么不好?关于单件的讨论。