Синглтон дизайн шаблон
Если вы на некоторое время написали код, вы должны столкнуться с шаблонами дизайна. Самое простое из них – синглтон. От Википедия :
Узор Singleton – это шаблон дизайна программного обеспечения, который ограничивает создание экземпляра класса на один объект.
Вы должны использовать шаблон Singleton, когда ваше приложение нуждается в доступе по всему миру, ленивый заряженный объект, который имеет только один экземпляр.
Некоторые люди могут сказать вам, что использование синглтона в Python строго ненужно. Ну, это просто не так. Необходимость решения всегда зависит от проблемы. Если вам нужен только глобальный доступ к объекту, вы можете использовать глобалы. Если вам не волнует ленивую загрузку, вы можете использовать модуль или «статический» класс. Есть много возможностей. На мой взгляд – если он подходит, и это заставляет ваш код приятнее, иди на это. От Дзэн Питона :
” Красивая лучше, чем уродливая. “
” Если реализация легко объяснить, это может быть хорошая идея ».
Выполнение
Если вы Google «Python Singleton», вы найдете много разных реализаций для рисунка Singleton. Этот – мой любимый:
class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls]
Метакласс может настроить процесс создания другого класса. Это может быть немного запутанным, так как это одна из магических особенностей, которые Python и большинство языков программирования не имеют. По сути, это класс класса. Смущенный? Давайте проведем небольшой эксперимент и попытаюсь понять, что происходит.
Это магия!
Давайте попробуем следующий код:
class MyMeta(type): def __call__(cls, *args, **kwargs): print('meta!') class MyClass(metaclass=MyMeta): def __init__(self): print('class') if __name__ == '__main__': c = MyClass() print(c)
Здесь мы определили метакласс, который печатает «метакласс» и класс, который печатает класс. Обратите внимание, что мы переоцениваем волшебную функцию __call__ Отказ __call__ Функция выполняется всякий раз, когда вы звоните на объект. В аспекте классов это означает, что MyClass () эквивалентно Мои занятия. Звоните () .
Код выше выводит следующее:
meta! None
Так.. Почему переменная C на самом деле нет …? Это происходит потому, что наш __call__ Функция ничего не возвращает. Довольно круто верно? Вы можете развить своих друзей и сделать их код не работать, пока не найдут определение метакласса (пожалуйста, не!:))
Давайте пойдем вперед и исправить это __call__ Функция:
class MyMeta(type): def __call__(cls, *args, **kwargs): print('meta!') return super(MyMeta, cls).__call__(*args, **kwargs) # call the class's __call__ manually class MyClass(metaclass=MyMeta): def __init__(self): print('class') if __name__ == '__main__': c = MyClass() print(c)
Этот код выводы:
meta! class <__main__.MyClass object at 0x7f43fa218898>
Успех! Мы настроили процесс создания классов. Теперь мы можем понять наш Singleton Metaclass намного лучше. Метакласс делает один экземпляр и возвращает, что всякий раз, когда вы называете класс. Вы можете сделать все, что приходит на ум с __call__ Функции, Python не очень ограничительный. Тем не менее, вы должны быть очень осторожны. Как мы знаем, код более читается, чем написано, а интуитивность важно.
Когда магия становится вуду
Там недостаток в реализации Metaclass Singleton, это неявно. Рассмотрим следующий пример (MyClass – наш синглтон от ранее):
# lots of code here c = MyClass() def some_function(): # some code a = MyClass() # some more code # lots of code class AnotherClass(object): def __init__(self, *args): self._d = MyClass() # more code # you got it.. more code
Мы используем нашу новую реализацию Singleton в большом проекте, возможно, даже десятки тысяч строк кода. Теперь новый кодер присоединяется к команде и читает код. Как вы думаете, он/она сможет легко сказать, что MyClass это синглтон? Ответ на это не в 99% случаев. Итак, что мы можем сделать, чтобы сделать наш синглтон более явным? Вот одно решение:
class MyClass(metaclass=MyMeta): def __init__(self): print('class') @classmethod def get_instance(cls): return MyClass() # instead of calling MyClass() we'll call MyClass.get_instance()
get_instance Метод класса делает очень ясно, что это на самом деле синглтон. Конечно, вы могли бы позвонить MyClass () И это даст вам тот же результат. Тем не менее, сделать ваш код более явным, как правило, делает его более легко понять.
Резюме
Я надеюсь, что вы поделитесь своим мнением о Singletons, Magic и Voodoo. Конечно, если вы этого не сделаете, я буду очень рад услышать об этом.
Я надеюсь, что вам понравилось, и как всегда, не стесняйтесь комментировать или поделиться. Спасибо за чтение.
Оригинал: “https://dev.to/asaf_g6/python-and-the-magic-singleton-4345”