dict.setdefault() используется, когда значение уже существует
Я пытаюсь добавить новые ключи в существующий словарь, устанавливая в качестве значения по умолчанию значение предыдущего ключа.
def check_data(end, start, profile):
print(profile)
for day in range((end-start).days+1):
profile.setdefault(start+datetime.timedelta(day),
{'expediture':0, 'top-up':0,
'budget':profile[start+datetime.timedelta(day-1)]['budget'] })
start = datetime.date(2019,2,1)
end = datetime.date(2019,2,17)
check_data(end, start, month_data)
вывод из print(profile)
:
{datetime.date(2019, 2, 1): {'expediture': 0, 'top-up': 0, 'budget': 100.0}}
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-4-e44462627692> in <module>
----> 1 check_data(end, start, month_data)
<ipython-input-2-90b936150b04> in check_data(end, start, profile)
20 profile.setdefault(start+datetime.timedelta(day),
21 {'expediture':0, 'top-up':0,
---> 22
'budget':profile[start+datetime.timedelta(day-1)]['budget'] })
23
24 def add_money(profile, topup, date=datetime.date.today()):
KeyError: datetime.date(2019, 1, 31)
Я не понимаю почему setdefault()
пытается установить значение по умолчаниюdatetime.date(2019, 2, 1)
если это значение уже существует.
Я мог бы решить эту проблему с if
но я хотел бы понять, как setdefault
работает и, возможно, есть альтернативное решение этой проблемы.
2 ответа
Подумайте, как бы вы написали этот код без setdefault
(и незначительный рефакторинг для удобства чтения):
def check_data(end, start, profile):
print(profile)
for day in range((end-start).days+1):
yesterday = start + datetime.timedelta(day - 1)
today = start + datetime.timedelta(day)
profile[today] = {
'expenditure': 0,
'top-up': 0,
'budget': profile[yesterday]['budget']
}
start = datetime.date(2019,2,1)
end = datetime.date(2019,2,17)
check_data(end, start, month_data)
На первой итерации цикла вам нужно значение profile[datetime(2019,1,31)]
для того, чтобы установить значение profile[datetime(2019,2,1)]
, но это значение никогда не было установлено.
Единственное использование для setdefault
здесь будет с ключом yesterday
при условии, что вы можете начать с какого-то общего профиля. Для простоты предположу, что budget
также целое число.
def check_data(end, start, profile):
print(profile)
for day in range((end-start).days+1):
yesterday = start + datetime.timedelta(day - 1)
today = start + datetime.timedelta(day)
profile[today] = {
'expenditure': 0,
'top-up': 0,
'budget': profile.setdefault(yesterday, {'budget': 0})['budget']
}
Сейчас если profile[yesterday]
не существует, setdefault
выполнит эквивалент profile[yesterday] = {'budget': 0}
перед возвратом этого значения.
Вы неправильно истолковали ошибку. KeyError
означает, что вы пытались найти ключ в словаре, но этот ключ не существует. В этом случае это выглядит как profile[start+datetime.timedelta(day-1)]
дает вам KeyError
и не имеет отношения к setdefault
вызов метода.