valerium
@valerium
Изобретая велосипед

Каким образом у разных объектов оказывается общим один параметр?

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

Немного кода.

Это "родительский" класс со словарём. Проверяем пустой словарь на заданный ключ, если не находим - создаём туда новый экземпляр. Если находим, вызываем метод вложенного объекта (он описан ниже).
class SomeClass:
    param = {}

    def add(self, data, value):
            if data not in self.param.keys():
                self.param[data] = SubClass()
            self.param[data].add(value)


Вот вложенный класс. Он хранит в себе множество, куда добавляет новые значения.
class SubClass:
    calls = set()

    def add(self,data):
        self.calls.add(data)


Потом заполняем кое-какими данными эту структуру.
>>> o = SomeClass()
>>> o.add('c', 1)
>>> o.add('c', 4)
>>> o.add('q', 2)
>>> o.add('q', 200)
>>> o.add('q', 19)
>>> o.add('a', 191)


А теперь проверяем, что же у нас внутри. Словарь содержит указатели на разные экземпляры класса.
>>> o.param 
{'a': <__main__.SubClass at 0x7f24401077b8>,
 'c': <__main__.SubClass at 0x7f24401076a0>,
 'q': <__main__.SubClass at 0x7f2440107710>}


Но при этом в параметрах разных экземпляров хранятся одни те же данные.
>>> o.param['a'].calls
{1, 2, 4, 12, 16, 17, 19, 191, 200}
>>> o.param['c'].calls
{1, 2, 4, 12, 16, 17, 19, 191, 200}
>>> o.param['q'].calls
{1, 2, 4, 12, 16, 17, 19, 191, 200}


ЧЯДНТ?
  • Вопрос задан
  • 282 просмотра
Решения вопроса 2
Kademn
@Kademn
Злой
Дело в том, что переменная `calls` объявлена в классе и ее наследуют все экземляры этого класса. И у них у всех, при создании, self.calls указывает на одно и тоже место в памяти, на оду и ту же переменную. Так как переменная в памяти это изменяемый объект, изменяя его в любом из экземпляров, вы видите измененный объект в любых других экземплярах, да и в самом классе тоже.
Если хотите, чтобы при создании экземпляра создавался новый объект в памяти, а не наследовался указатель, используйте __init__, который вызывается при создании экземпляра.
class SubClass(object):
    def __init__(self):
        self.calls = set()


Кстати сказать, что с классом SomeClass у вас абсолютно таже история. Изменяемый объект (словарь param), указатель на который наследуют все экземпляры.
Ответ написан
@throughtheether
human after all
ЧЯДНТ?
Используете атрибут класса, а не экземпляра класса.
Сделайте примерно так:
class SubClass:
    def __init__(self):
        self.calls=set()
    def add(self,data):
        self.calls.add(data)

И аналогично в SomeClass.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы