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 шт):
Можно так.
Методу 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)
в defaultdict можно передать ещё один defaultdict:
servers = defaultdict(lambda:defaultdict(int))
Такой код тоже работает:
from collections import defaultdict
servers = defaultdict(lambda:{'BytesSent':0,'BytesRcvd':0})
servers[sAddr]['BytesSent'] += int(sBytesSent)
servers[sAddr]['BytesRcvd'] += int(sBytesRcvd)