Рубрики
Без рубрики

Python и волшебный синглтон

Шаблон дизайна Singleton Если вы уже некоторое время пишу код, вы должны иметь … Помечено с Python, дизайн шаблонов.

Синглтон дизайн шаблон

Если вы на некоторое время написали код, вы должны столкнуться с шаблонами дизайна. Самое простое из них – синглтон. От Википедия :

Узор 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”