2017-02-14 26 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 следует избегать Singletons, и поэтому мне интересно, что лучше всего подходит для этого типа проблем?

+2

Подробнее о ** _ The Borg Design Pattern _ ** [здесь] (http://code.activestate.com/recipes/577870-singleton-we-dont-need-no-stinkin-singleton-the-bo/) и [здесь] (http://code.activestate.com/recipes/66531/) для простых способов преобразования класса в одноэлементный. Есть и другие способы. – martineau

+1

Я бы использовал сам класс как синглтон. У меня никогда не было проблем с этим подходом. – Alfe

+0

«Импорт SocketCommunication», который вы говорите в других модулях, не будет работать, потому что «SocketCommunication» - это имя одного из ваших классов. Это должно быть что-то вроде 'from my_module import SocketCommunication', чтобы следующая строка была действительной. Тем не менее, вы могли бы эффективно сделать класс singleton, добавляя 'SocketCommunication = SocketCommunication()' в файл 'my_module.py' после определения класса. Таким образом будет очень сложно создать еще несколько экземпляров, потому что имя класса будет переопределено экземпляром самого себя. – martineau

ответ

1

Ниже перечислены три способа использования singleton в Python. Использование metaclass и decorator для достижения цели.

  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

 Смежные вопросы

  • Нет связанных вопросов^_^