dict.setdefault () используется, когда значение уже существует - PullRequest
0 голосов
/ 15 февраля 2019

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

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 ]

0 голосов
/ 15 февраля 2019

Подумайте, как бы вы написали этот код без 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} перед возвратомэто значение.

0 голосов
/ 15 февраля 2019

Вы неправильно истолковали ошибку.KeyError означает, что вы пытались найти ключ в словаре, но этот ключ не существует.В этом случае похоже, что profile[start+datetime.timedelta(day-1)] дает вам KeyError и не связано с вызовом метода setdefault.

...