Моносостояние (Класс Борга) Каким образом все свойства одного экземпляра становятся свойствами других?

Объясните, пожалуйста, как это работает?

class Borg:
    _shared_state = {}

    def __init__(self):
        self.__dict__ = self._shared_state

Каким образом все свойства одно экземпляра становятся свойствами других? Здесь ведь каждый раз словарю аттрибутов экземпляра класса при инициализации должен присваиваться пустой словарь, а получается наоборот, не понимаю :(


Ответы (2 шт):

Автор решения: CrazyElf

Инициализируется словарь при создании класса, а не экземпляра класса. При создании экземпляра всем экземплярам присваивается ссылка на один и тот же словарь, с которым и работают в итоге все экземпляры.

Вот эта часть выполняется сразу, когда интерпретатор встречает объявление класса:

class Borg:
    _shared_state = {}

А эта - при создании каждого экземпляра класса:

def __init__(self):
    self.__dict__ = self._shared_state

Проверим, что ссылка получается на один и тот же объект:

class Borg:
    _shared_state = {}
    print(id(_shared_state))

    def __init__(self):
        self.__dict__ = self._shared_state
        print(id(self.__dict__))

a = Borg()
b = Borg()
c = Borg()

Вывод:

140386153522520
140386153522520
140386153522520
140386153522520

Тут есть ещё одна тонкость. Когда выполняется строка:

self.__dict__ = self._shared_state

То вроде бы должно браться значение переменной _shared_state из экземпляра класса (ключевое слово self). Но своей такой переменной у экземпляра нет, поэтому берётся "статическая" переменная - из описания самого класса. Если в дальнейшем что-то присвоить переменной self._shared_state, то она перестанет указывать на статический объект класса и заживёт собственной жизнью, это нужно знать.

→ Ссылка
Автор решения: Geniusmediocrity

Так получается потому что. Объект класса _shared_state ссылается на одну ячейку памяти(допустим "а") и когда мы пишем:

def __init__(self):
    self.__dict__ = self._shared_state

то у нас объект ЭК __dict__ ссылается на тот же объект в памяти компьютера, то есть (как я писал ранее) в нашем случае объект "а".

Это получается потому что мы self.__dict__ присваиваем не значение атрибута _shared_state, а лишь ссылку на объект в памяти компьютера в которой он хранится, а как мы знаем если мы присваиваем одной переменной ссылку на другую переменную, то эти две переменные всегда будут хранить одинаковые значения, пока ссылка на объект в памяти не будет удалена.

Почитать подробнее про память ПК можно stackoverflow или habr

→ Ссылка