На этом занятии мы
рассмотрим реализацию паттерна «Моносостояние», реализуемое на уровне классов и
объектов. На примере этого паттерна я хочу вам показать, как можно в Python легко и гибко
управлять локальными атрибутами экземпляров класса.
Вначале разберем
саму идею «Моносостояния». Представьте, что у нас некий многопоточный процесс и
в каждом потоке создается свой экземпляр класса ThreadData. Но нам бы
хотелось, чтобы все они имели единые локальные свойства:
Обратите
внимание, имели бы именно единые локальные свойства, а не просто одни и те же
данные, то есть, их словарь __dict__ был бы одинаков для всех этих
экземпляров.
Реализуется на Python это очень
просто. Объявим класс и в нем пропишем приватный словарь с некоторыми
начальными свойствами, которыми будет обладать каждый экземпляр (или же этот
словарь может быть пустым):
class ThreadData:
__shared_attrs = {
'name': 'thread_1',
'data': {},
'id': 1,
}
def __init__(self):
self.__dict__ = self.__shared_attrs
Затем, в инициализаторе
этого класса, переопределим специальную коллекцию __dict__ на общий
словарь __shared_attrs. Таким образом,
коллекция __dict__ в каждом
экземпляре будет ссылаться на один и тот же словарь класса __shared_attrs, а значит, все
они будут иметь общие локальные свойства.
Я напомню, что
список локальных свойств каждого конкретного экземпляра класса определяется
словарем __dict__ и если у всех
объектов он будет един, то едины окажутся и их локальные свойства.
Давайте
посмотрим, как это будет работать. Создадим экземпляр класса th1:
В консоли можно
видеть, что автоматически были созданы свойства экземпляра: name, data и id, как раз те,
что прописаны в словаре __shared_attrs.
Создадим второй
экземпляр:
Видим, что у
него те же самые свойства по умолчанию. Причем, эти свойства воспринимаются как
локальные. Поэтому, если их переопределить, например:
то изменения
коснутся именно словаря __shared_attrs и все объекты
класса ThreadData также изменят значение этого атрибута.
Также мы можем
совершенно свободно создавать новые свойства:
th1.attr_new = 'new attr'
и оно появляется
во всех экземплярах этого класса.
Вот так реализуется
паттерн «Моносостояние» на языке Python. Возможно, у вас здесь остался
вопрос, а где все это используется? Честно говоря, паттерн «Моносостояние» мне
ни разу не приходилось применять. Я привел его здесь, так как он хорошо
показывает, как гибко можно управлять поведением объектов класса за счет
переопределения ссылки стандартного свойства __dict__ в каждом
экземпляре, чтобы он вел на общий словарь __shared_attrs. Меняя эту
коллекцию, оказывается можно существенно менять стандартное поведение
экземпляров класса касательно их локальных атрибутов. Это и было целью данного
занятия. Расширить ваше понимание о работе с атрибутами объектов классов. И,
надеюсь, мне это удалось.