2017-02-14 12 views
2

私は、サーバーとのソケット通信を含むPythonアプリケーションを作成しています。私はアプリケーション全体(いくつかの他のモジュール)で使用できるモジュールを用意したいと思います。現在、私のモジュールは、次のようになります。私は他のモジュールでこれを使用すると、私は次の操作を行い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では避けなければならないので、このタイプの問題のベストプラクティスは何か不思議です。

+2

** _ボルグデザインパターン_ ** [ここをクリック](http://code.activestate.com/recipes/577870-singleton-we-dont-need-no-stinkin-singleton-the-bo/ )と[here](http://code.activestate.com/recipes/66531/)を参照して、クラスをシングルトンに簡単に変換する方法を説明します。同様に、他の方法もあります。 – martineau

+1

私はシングルトンとしてクラス自体を使用したいと思います。私はこのアプローチに問題はなかった。 – Alfe

+0

'SocketCommunication'があなたのクラスの名前であるため、あなたが他のモジュールで言う' import SocketCommunication'は動作しません。次の行を有効にするには 'from my_module import SocketCommunication'のようなものでなければなりません。つまり、クラスが定義された後、 'my_module.py'ファイルに' SocketCommunication = SocketCommunication() 'を追加することで、クラスを効果的にシングルトンにすることができます。そうすれば、クラス名がそれ自身のインスタンスで上書きされるので、それ以上のインスタンスを作成することは非常に困難です。 – martineau

答えて

1

次は、シングルトンをPythonで使用する3つの方法です。 metaclassdecoratorを使用して目標を達成してください。

  1. 使用__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 
    
  2. 使用__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 
    
  3. 使用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を使用することをお勧めします。

0

シングルトンはグローバル変数を包む方法としてよく使われるため、議論の余地があります。これが理由のひとつです。グローバル化はテストをより困難にし、アクセス制御を制限し、しばしば変数間の強力な結合につながります。あなたは、単にむしろ、SocketCommunication初期化された複数回(正当な理由のために)を停止しようとしているので、シングルトンを使用することが最も可能性の高い適切である、あなたの特定のシナリオでは

(グローバルは、一般的に悪い習慣です理由として、より詳しくは、http://wiki.c2.com/?GlobalVariablesAreBadを参照してください)これをグローバルな状態のコンテナとして使用しようとするよりも、

シングルトンについてのいくつかの議論については、Are Singletons really that bad?およびWhat is so bad about singletons?を参照してください。

+0

あなたの答えをありがとう。この特定のケースでは、クラスのインスタンスを1つだけ必要とするときに、シングルトンが最適なソリューションと思われます。 – user3170354

関連する問題