2017-02-14 4 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() 

문제를 내가이 작업을 수행 할 때마다이 새 연결이 생성되어있는 것 서버에 새로운 클라이언트로 표시되기 때문에 바람직하지 않습니다. 내가 읽을 수있는 것부터, 싱글 톤은 파이썬에서 피해야하며, 따라서 이런 유형의 문제에 대한 모범 사례는 무엇인지 궁금하다.

+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

다음은 파이썬에서 싱글 톤을 사용하는 세 가지 방법입니다. 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

싱글 톤은 전역 변수를 감싸는 방법으로 자주 사용되기 때문에 논쟁의 여지가 있습니다. 이것이 일부 사람들이 회피를 옹호하는 이유입니다. 전역 변수는 테스트를 더욱 어렵게 만들고, 액세스 제어를 제한하며, 종종 변수 간의 강력한 결합으로 이어집니다. (일반적으로 왜 일반적으로 전역 변수를 사용하는 이유에 대한 자세한 내용은 http://wiki.c2.com/?GlobalVariablesAreBad을 참조하십시오)

SocketCommunication을 여러 번 (정당한 이유로) 초기화하지 않으려 고하기 때문에 특정 시나리오에서 가장 가능성이 높습니다. 글로벌 상태의 컨테이너로 사용하려는 것보다

싱글 톤에 대한 설명은 Are Singletons really that bad?What is so bad about singletons?을 참조하십시오.

+0

답변 해 주셔서 감사합니다.이 특별한 경우에는 클래스의 단일 인스턴스 만 필요할 때 싱글 톤이 최상의 솔루션 인 것으로 보입니다. – user3170354