Python, многомерные списки и типы данных. Как будет идиоматично?

Для решения одной несрочной задачки решил попробовать в python. Задачка состоит в сборе статистики по логам. Поскольку я в python немножко не в зуб ногой, код у меня получается рабочий, но странный. Вот кусок - есть двумерный dict, в который дописываются ключи с адресами по мере их появления в логе, а в содержимое записывается статистика и её надо суммировать с тем, что уже есть:

servers = defaultdict(dict)
...
if not sAddr in servers.keys():
    servers[sAddr] = {
        'BytesSent': int(sBytesSent),
        'BytesRcvd': int(sBytesRcvd)
    }
else:
    servers[sAddr]['BytesSent'] += int(sBytesSent)
    servers[sAddr]['BytesRcvd'] += int(sBytesRcvd)

Хочется избавиться от условия, то есть оставить (условно) просто

servers[sAddr]['BytesSent'] += int(sBytesSent)

и, если ключа нет, то он создаётся, а в него записывается значение. В общем, чтобы += работало как для скаляров. Есть какой-то хитрый или не очень способ создавать ключи по мере обращения? Или как это написать по-питоновски правильно?


Ответы (3 шт):

Автор решения: n1tr0xs

Можно так.
Методу get можно задать значение, которое он вернет, если ключ не будет найден.

from collections import defaultdict
servers = defaultdict(dict)

servers[sAddr]['BytesSent'] = ser['sAddr'].get('ByteSent', 0) + int(sBytesSent)
servers[sAddr]['BytesRcvd'] = ser['sAddr'].get('ByteSent', 0) + int(BytesRcvd)

А можно создать свою функцию, которая будет возвращать словарь.

from collections import defaultdict

def my_default():
    return {
        'BytesSent': 0,
        'BytesRcvd': 0,
        }
    
servers = defaultdict(my_default)

servers[sAddr]['BytesSent'] += int(sBytesSent)
servers[sAddr]['BytesRcvd'] += int(sBytesRcvd)
→ Ссылка
Автор решения: Danis

в defaultdict можно передать ещё один defaultdict:

servers = defaultdict(lambda:defaultdict(int))
→ Ссылка
Автор решения: SergFSM

Такой код тоже работает:

from collections import defaultdict

servers = defaultdict(lambda:{'BytesSent':0,'BytesRcvd':0})
servers[sAddr]['BytesSent'] += int(sBytesSent)
servers[sAddr]['BytesRcvd'] += int(sBytesRcvd)
→ Ссылка