Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 5, 2017 09:31:09

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

 class DeepDict(dict):
    def __init__(self, *args, **kwargs):
        self.default = kwargs.pop("default")
        super(DeepDict, self).__init__(*args, **kwargs)
    def __getitem__(self, item):
        try:
            value = super(DeepDict, self).__getitem__(item)
            if isinstance(value, dict):
                return DeepDict(value, default=self.default)
            else:
                return value
        except KeyError:
            return self.default
    def __repr__(self):
        return "DeepDict: {}".format(super(DeepDict, self).__repr__())
dct = {"a": {"b": {"c": 0}}}
d = DeepDict(dct, default=10)
print(d["a"]["b"]["c"])
print(d["a"]["FF"])



Офлайн

#2 Янв. 5, 2017 09:40:11

worldmind
Зарегистрирован: 2016-12-20
Сообщения: 12
Репутация: +  0  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

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

 context = {**defaults, **user}
а для старых питонов
 context = defaults.copy()
context.update(user)

upd: Похоже это для вложенных не работает

Отредактировано worldmind (Янв. 5, 2017 09:47:09)

Офлайн

#3 Янв. 5, 2017 09:45:23

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

ABKorotky
Правда, для рекурсивной инициализации не совсем подходит

А в чем проблема?
 d = defaultdict(lambda:defaultdict(list))

По теме можно нагородть костыли
http://stackoverflow.com/questions/7088009/python-try-except-as-an-expression

те можно пользоваться так:
 v = TE(lambda: x[2][3], 2)

А вообще вам надо следить за судьбой:
https://www.python.org/dev/peps/pep-0463/



Отредактировано doza_and (Янв. 5, 2017 10:01:14)

Офлайн

#4 Янв. 5, 2017 09:45:53

worldmind
Зарегистрирован: 2016-12-20
Сообщения: 12
Репутация: +  0  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

worldmind
Подумал, что наверно более правильный способ не с отдельными полями работать, а определять структуру со значениями по умолчанию, тогда наверно такой вариант будет правильным
А, тут подсказывают что со вложенными так не сделать

Отредактировано worldmind (Янв. 5, 2017 09:48:37)

Офлайн

#5 Янв. 5, 2017 10:33:41

ABKorotky
Зарегистрирован: 2017-01-05
Сообщения: 2
Репутация: +  0  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

Никто и не говорит, что есть проблема )
Насколько я понял изначальные условия сей ишью - нужно иметь механизм установки дефолтного значения для словаря некоторой структуры.

И вариантов действительно 100500!
Всё зависит от потребностей.

1) Простой словарь с единичным уровнем вложенности ключей.
Вариантов предложили массу, начиная от использования .get(), .update(), .setdefault() - выбирай любой!
Какие-то варианты потребуется везде по коду юзать. Это я про .get() и .setdefault(). Это нехорошо потому как логика алгоритма будет “размазываться” логикой доступа к ключам.
Варианты с .update() будет интересен при инстанцировании. Профит в атомарности и разовости такой операции.

2) Более сложный вариант с известной структурой и известным уровнем вложенности. Подойдут те же операции, что обозначены выше. Нужно будет позаботиться только о том, чтобы при создании под-словаря передать ему необходимое дефолтное значение.

3) Обобщённый вариант: есть некая структура дефолтных значений произвольной вложенности. Вот тут будут интересны вариации DeepDict, предложенные FishHook (сам что-то похожее велосипедил). Чем хорош этот подход: логика доступа к ключам (и вложенным) будет инкапсулирована в недрах класса, и в месте использования не придётся “разбодяживать” основной алгоритм разного рода проверками - ты просто обращается к ключу и будешь уверен, что получишь дефолтное значение.

Что же касается новых фишечек, то тут очень сильно зависит от степени “старости” проекта и зависимостях на внешние пакеты. Далеко не все проекты могут похвастаться использованием в проде пайтона версии даже 3.5 с async def вместо @coroutine и прочими новшествами (async for сюда же)

Офлайн

#6 Янв. 5, 2017 10:36:30

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

раз обсуждение продолжается поясню

 def TE(f, default_value):
    try:
        return f()
    except:
        return default_value
a={2:{3:"a"}}
b=TE(lambda: a[2][4], 45)

Не очень красивый костыль но довольно простой.

Это очевидно не defaultdict а именно то что просил автор в начале. Некий оператор который в случае неудачи вычисления любого выражения (не обязательно словаря или вложенного словаря) возвращает значение по умолчанию.

Работать очевидно будет в любом питоне. Но получается несколько многословно.



Отредактировано doza_and (Янв. 5, 2017 10:41:45)

Офлайн

#7 Янв. 5, 2017 11:00:28

worldmind
Зарегистрирован: 2016-12-20
Сообщения: 12
Репутация: +  0  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

doza_and
раз обсуждение продолжается поясню
ну я такой выше и делал, только в и инфиксной форме

Офлайн

#8 Янв. 5, 2017 11:02:31

worldmind
Зарегистрирован: 2016-12-20
Сообщения: 12
Репутация: +  0  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

Но сейчас я согласен с тем, что наверно мердж двух вложенныйх хешей это даже более удобный вариант, да только не нахожу в питоне готовой функции для этого

Офлайн

#9 Янв. 5, 2017 11:38:11

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

worldmind
ChainMap ?

Офлайн

#10 Янв. 5, 2017 11:46:53

worldmind
Зарегистрирован: 2016-12-20
Сообщения: 12
Репутация: +  0  -
Профиль   Отправить e-mail  

Аналог перлового оператора defined-or

4kpt_IV
worldmindChainMap ?
надо глянуть
пока нашёл такое решение
 >>> import dpath.util
>>> from copy import deepcopy
>>> default_struct = {'key': {'key1': 0, 'key2': 0}}
>>> struct = {'key': {'key1': 666}}
>>> merged = deepcopy(default_struct)
>>> dpath.util.merge(merged,struct)
>>> merged
{'key': {'key1': 666, 'key2': 0}}

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version