Что знаешь про singleton
Паттерн Одиночка (Синглтон) применяется, когда необходим класс, у которого должен быть единственный экземпляр во всей программе.
С помощью паттерна Одиночка могут быть реализованы многие паттерны (абстрактная фабрика, строитель, прототип).
В сборнике рецептов приводится простой класс Singleton, которому любой класс может унаследовать, чтобы стать одиночкой.
class Singleton(object):
def __new__(cls,*dt,**mp):
if not hasattr(cls,'_inst'):
cls._inst = super(Singleton, cls).__new__(cls,dt,mp)
else:
def init_pass(self,*dt,**mp):pass
cls.__init__ = init_pass
return cls._inst
if __name__ == '__main__':
class A(Singleton):
def __init__(self):
"""Super constructor
There is we can open file or create connection to the database
"""
print "A init"
a1 = A()
a2 = A()
И класс Borg, который даст тот же результат совсем другим способом.
class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
self.state = 'Init'
def __str__(self):
return self.state
class YourBorg(Borg):
pass
def main():
"""
>>> rm1 = Borg()
>>> rm2 = Borg()
>>> rm1.state = 'Idle'
>>> rm2.state = 'Running'
>>> print('rm1: {0}'.format(rm1))
rm1: Running
>>> print('rm2: {0}'.format(rm2))
rm2: Running
# When the `state` attribute is modified from instance `rm2`,
# the value of `state` in instance `rm1` also changes
>>> rm2.state = 'Zombie'
>>> print('rm1: {0}'.format(rm1))
rm1: Zombie
>>> print('rm2: {0}'.format(rm2))
rm2: Zombie
# Even though `rm1` and `rm2` share attributes, the instances are not the same
>>> rm1 is rm2
False
# Shared state is also modified from a subclass instance `rm3`
>>> rm3 = YourBorg()
>>> print('rm1: {0}'.format(rm1))
rm1: Init
>>> print('rm2: {0}'.format(rm2))
rm2: Init
>>> print('rm3: {0}'.format(rm3))
rm3: Init
"""
if __name__ == "__main__":
import doctest
doctest.testmod()
Однако самый простой способ получить функциональность одиночки в Python - создать модуль с глобальным состоянием, которое хранится в закрытых переменных, и предоставить открытые функции для доступа к нему. Например, для получения курсов валют нам понадобится функция, которая будет возвращать словарь (ключ - название валюты, значение - обменный курс). Возможно, эту функцию понадобится вызывать несколько раз, но в большинстве случев извлекать откуда-то курсы нужно единожды. Реализовать это поможет паттерн Одиночка.
def get(refresh=False):
if refresh:
get.rates = {}
if get.rates:
return get.rates
with urllib.request.urlopen(_URL) as file:
for line in file:
line = line.rstrip().decode("utf-8")
if not line or line.startswith(("#", "Date")):
continue
name, currency, *rest = re.split(r"/s*,/s*", line)
key = "{} ({})".format(name, currency)
try:
get.rates[key] = float(rest[-1])
except ValueError as err:
print("error {}: {}".format(err, line))
return get.rates
get.rates = {}
if __name__ == "__main__":
import sys
if sys.stdout.isatty():
print(get())
else:
print("Loaded OK")
Здесь мы создаем словарь rates в виде атрибута функции Rates.get() - это наше закрытое значение. Когда открытая функция get() вызывается в первый раз (а также при вызове с параметром refresh=True), мы загружаем список курсов; в противном случае просто возвращаем последние загруженные курсы.
Oct. 9, 2023, Источник
Singleton - это паттерн проектирования, который гарантирует, что класс имеет только один экземпляр, и предоставляет глобальную точку доступа к нему.
Основные характеристики singleton:
1. Одиночный экземпляр: У класса есть только один экземпляр, который создается при первом обращении к нему, а затем повторно используется при последующих вызовах.
2. Глобальный доступ: Singleton предоставляет глобальную точку доступа к своему экземпляру, что позволяет другим объектам получить доступ к этому экземпляру через общедоступный метод или свойство.
3. Ленивая инициализация: Экземпляр класса создается только при первом обращении к нему, а не заранее, что позволяет оптимизировать использование ресурсов и избегать ненужного создания объектов.Пример реализации singleton:
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# Использование
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # Вывод: True, потому что s1 и s2 ссылаются на один и тот же экземпляр класса Singleton
В этом примере метод `__new__` переопределяется таким образом, чтобы при первом вызове он создавал новый экземпляр класса, а при последующих вызовах возвращал уже созданный экземпляр. Таким образом, у класса Singleton всегда есть только один экземпляр.
Feb. 16, 2024, easyoffer