Вложенные словари в классах

Я испытываю неожиданное поведение в этой структуре данных.

class IncomeVerification(object): data = {'IncomeYears': []} def __init__(self, income_years): for year in income_years: new_year = IncomeYear(year).data self.data['IncomeYears'].append(new_year) class IncomeYear(object): data = {'IncomeYear': {'Year': None}} def __init__(self, year, reported_income=None): self.data['IncomeYear']['Year'] = year income_years = ['2014', '2013', '2012', '2011'] foo = IncomeVerification(income_years) print foo.data 

Это возвращает,

  {'IncomeYears': [{'IncomeYear': {'Year': '2011'}}, {'IncomeYear': {'Year': '2011'}}, {'IncomeYear': {'Year': '2011'}}, {'IncomeYear': {'Year': '2011'}}]} 

Я ожидаю,

  {'IncomeYears': [{'IncomeYear': {'Year': '2014'}}, {'IncomeYear': {'Year': '2013'}}, {'IncomeYear': {'Year': '2012'}}, {'IncomeYear': {'Year': '2011'}}]} 

Я считаю, что вложенный характер моих словарей создает уникальные ключевые проблемы и, следовательно, перезаписывает существующие записи. Любые идеи о том, как изменить вызов выше, чтобы получить желаемый результат?

Спасибо.

Вы повторно добавляете ссылки не в новый dict/object с self.data['IncomeYears'].append(new_year) в своем собственном коде, поэтому в любое время, когда вы делаете изменения, вы фактически меняете один и тот же объект.

Вам нужно будет делать deepcopy данные с помощью собственного кода:

 from copy import deepcopy class IncomeVerification(object): data = {'IncomeYears': []} def __init__(self, income_years): for year in income_years: new_year = deepcopy(IncomeYear(year).data) 

Что будет выводить:

 {'IncomeYears': [{'IncomeYear': {'Year': '2014'}}, {'IncomeYear': {'Year': '2013'}}, {'IncomeYear': {'Year': '2012'}}, {'IncomeYear': {'Year': '2011'}}]} 

Или лучше снова сделать data атрибутом экземпляра в IncomeYear в отличие от атрибута класса, который в настоящее время существует, который создается один раз и разделяется между всеми экземплярами:

 class IncomeVerification(object): data = {'IncomeYears': []} def __init__(self, income_years): for year in income_years: new_year = IncomeYear(year).data self.data['IncomeYears'].append(new_year) class IncomeYear(object): def __init__(self, year, reported_income=None): # new dict/object for each instance self.data = {'IncomeYear': {'Year': None}} self.data['IncomeYear']['Year'] = year income_years = ['2014', '2013', '2012', '2011'] foo = IncomeVerification(income_years) print(foo.data) 

Что снова выводит:

 {'IncomeYears': [{'IncomeYear': {'Year': '2014'}}, {'IncomeYear': {'Year': '2013'}}, {'IncomeYear': {'Year': '2012'}}, {'IncomeYear': {'Year': '2011'}}]} 

атрибуты класса vs экземпляра

Это происходит потому, что атрибут data в ваших классах – это переменные класса , которые ведут себя как статические атрибуты с других языков программирования, поскольку они уникальны для класса, а не для каждого из его экземпляров.

Чтобы ваш код работал, вы должны сделать их переменными экземпляра , переместив их в свой метод __init__() , например:

 class IncomeVerification(object): def __init__(self, income_years): self.data = {'IncomeYears': []} for year in income_years: new_year = IncomeYear(year).data self.data['IncomeYears'].append(new_year) class IncomeYear(object): def __init__(self, year, reported_income=None): self.data = {'IncomeYear': {'Year': None}} self.data['IncomeYear']['Year'] = year income_years = ['2014', '2013', '2012', '2011'] foo = IncomeVerification(income_years) print foo.data 

Выполнение этого будет возвращено:

 {'IncomeYears': [{'IncomeYear': {'Year': '2014'}}, {'IncomeYear': {'Year': '2013'}}, {'IncomeYear': {'Year': '2012'}}, {'IncomeYear': {'Year': '2011'}}]} 

Как и ожидалось.