I'm trying to add new keys to the existing dictionary, setting as default value, the value of the previous key.
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)
output from 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)
I don't understand why setdefault()
tries to set default value to datetime.date(2019, 2, 1)
if this value already exists.
I could fix this problem with if
but I'd like to understand how setdefault
works and maybe there is alternative solution for this problem.
You are misinterpreting the error. A KeyError
means you tried to look up a key in a dictionary but that key does not exist. In this case it looks like profile[start+datetime.timedelta(day-1)]
is giving you the KeyError
and is not related to the setdefault
method call.
Consider how you would write this code without setdefault
(and some minor refactoring for readability):
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)
On the first iteration of the loop, you need the value of profile[datetime(2019,1,31)]
in order to set the value of profile[datetime(2019,2,1)]
, but that value was never set.
The only use for setdefault
here would be with the key yesterday
, assuming you could start with some generic profile. For simplicity, I'll assume that budget
is also an integer.
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']
}
Now, if profile[yesterday]
doesn't already exist, setdefault
will execute the equivalent of profile[yesterday] = {'budget': 0}
before returning that value.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.