Класс создания экземпляра сохраняет ссылки

#python #class #object #reference

#python #класс #объект #ссылка

Вопрос:

В Python я создаю экземпляр класса дважды и сохраняю их в 2 разных переменных. Почему второй объект содержит копию первого объекта? Я знаю, что это копия, потому что я меняю значения в одном объекте, и это не меняет другого. Пример:

У меня есть следующий класс:

 class HistoricalData:
    dataPoints = {}
 

Затем я создаю экземпляр класса и заполняю точки данных значениями:

 hd1 = HistoricalData()
hd1.dataPoints["channel1"] = 1
hd1.dataPoints["channel2"] = 2
hd1.dataPoints["channel3"] = 3
 

Затем я снова создаю экземпляр класса и снова заполняю его значениями:

 hd2 = HistoricalData()
hd2.dataPoints["channel1"] = 10
 

Когда я печатаю значения из hd1.DataPoints и hd2.DataPoints, я получаю следующее:

 {'channel1': 1, 'channel2': 2, 'channel3': 3}
{'channel1': 10, 'channel2': 2, 'channel3': 3}
 

Словарь имеет копию первого во втором объекте, потому что значение в channel1 было изменено во втором, но не в первом.

Я думал, что при создании экземпляра класса все значения по умолчанию будут соответствовать тому, что было определено в классе. Я что-то упускаю?

Комментарии:

1. Вы где-то допустили ошибку. Ответ Johhnyweb верен, насколько это возможно, но вы наверняка увидите, что значение изменено на 10 in dataPoints для обоих экземпляров, если вы запустите приведенный выше код. Существует только один словарь. «Я знаю, что это копия, потому что я меняю значения в одном объекте, и это не меняет другого». — ну, это просто не тот случай.

Ответ №1:

Вы объявили class переменную, а не переменную экземпляра.

Переменные класса являются общими для всех экземпляров class . Это означает, что когда вы обновляете один HistoricalData object , вы обновляете их все.

Переменные экземпляра являются локальными для каждого экземпляра a class . Обычно они инициализируются в __init__() специальном методе, который вызывается при создании каждого экземпляра.

Таким образом, вам, вероятно, следует инициализировать datapoints так, чтобы получить желаемые результаты:

 class HistoricalData(object):

    def __init__(self):
        self.dataPoints = {}
 

Комментарии:

1. Если бы я добавил новую переменную экземпляра с простым типом, например, string, нужно ли было бы это также определять в init ?

2. @DannyTsang: Дело не в простоте типов. self.name = '' в равной степени необходимо было бы инициализировать в __init__() (или аналогично), чтобы быть переменной экземпляра .

3. @DannyTsang: Рад помочь. Добро пожаловать в сообщество StackOverflow!