Комментарии 8
Батенька да вы же гигант мысли, да это же просто гениальное изобретение, не знаю, как я мог жить без этого, ведь {}.get('key',None) так не удобен…
Дамс дожили, написал велосипед в ~100 строках — выложил на хабр. Что дальше? Будем стандартную библиотек изобретать?
Дамс дожили, написал велосипед в ~100 строках — выложил на хабр. Что дальше? Будем стандартную библиотек изобретать?
Этот класс не претендует на вселенское открытие или всепоглощающую сингулярность.
Просто мне показалось, что вот так писать — это не по-питоновски:
Хотелось вот так:
P.S. {}.get('key',None) — не то делает, что мне нужно.
Просто мне показалось, что вот так писать — это не по-питоновски:
data = {}
data.setdefault('departments', {}).setdefault(sale.user.department.pk, {}).setdefault('users', {}).setdefault('sale.user.pk', {}).setdefault('rows', {}).setdefault(sale.pk, {}) = {...}
Хотелось вот так:
data = ElasticDict()
data.departments[sale.user.department.pk].users[sale.user.pk].rows[sale.pk] = {...}
P.S. {}.get('key',None) — не то делает, что мне нужно.
Выглядит, конечно, диковато, но
from collections import defaultdict
data = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(dict)))))
data['departments'][sale.user.department.pk]['users']['sale.user.pk']['rows'][sale.pk] = {...}
Можно рекурсивно:
from collections import defaultdict
recdict = lambda: defaultdict(recdict)
data = recdict()
data["qwe"]["asd"] = 123
Спасибо за идеи, мне вот еще одну подкинули в issue:
И дали ссылку на более продвинутую реализацию моего подхода: addict
from collections import defaultdict
class DotDict(defaultdict):
def __getattr__(self, attr):
return self.__getitem__(attr)
def __setattr__(self, attr, val):
return self.__setitem__(attr, val)
def ElasticDict():
return DotDict(ElasticDict)
data = ElasticDict()
data.divisions.sales.persons[123].name = 'Alex'
print data.divisions.sales.persons[123].name
И дали ссылку на более продвинутую реализацию моего подхода: addict
>P.S. {}.get('key',None) — не то делает, что мне нужно.
в статье:
>>1. доступ к атрибутам можно было делать без квадратных скобочек
>> 2. автоматически создавались отсутствующие аттрибуты
в статье:
>>1. доступ к атрибутам можно было делать без квадратных скобочек
>> 2. автоматически создавались отсутствующие аттрибуты
Проверка словарей на наличие ключей или использование setdefatult(key, {}) превращает код в нечитабельную кашу.
Окей, давайте сравним. Ваше решение:
from elasticdict import ElasticDict
data = ElasticDict()
for sale in Sale.objects.filter(...).prefetch_related(...):
data.departments[sale.user.department.pk].users[sale.user.pk].rows[sale.pk] = {
'base_income': sale.amount,
'bonus': sale.calc_bonus()
}
Решение в лоб, без каких-либо зависимостей, даже без стандартного defaultdict:
data = {'departaments': {}}
for sale in Sale.objects.filter(...).prefetch_related(...):
departament = data['deparaments'].setdefault(sale.user.department.pk, {'users': {}})
user = departament['users'].setdefault(sale.user.pk, {'rows': {}})
user['rows'][sale.pk] = {
'base_income': sale.amount,
'bonus': sale.calc_bonus()
}
Вопрос автору: оно того стоило?
Согласен, ради конкретно такого примера не стоило бы.
В моей задаче строчек для вставки в словарь сильно больше (30+), вдобавок, есть внутренняя логика if/else.
Создание промежуточных переменных не добавляет читаемости.
Я не настаиваю, что мой код абсолютно более читаемый, но найдутся те, кто со мной согласятся.
Равно как найдутся те, кто скажет, что это отстой — и последних в 4 раза больше :)
В моей задаче строчек для вставки в словарь сильно больше (30+), вдобавок, есть внутренняя логика if/else.
Создание промежуточных переменных не добавляет читаемости.
Я не настаиваю, что мой код абсолютно более читаемый, но найдутся те, кто со мной согласятся.
Равно как найдутся те, кто скажет, что это отстой — и последних в 4 раза больше :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Как я переизобрел словари в Python