Предположим, мне нужна PERL-подобная автовивикация в Python, т.е.:
>>> d = Autovivifier()
>>> d = ['nested']['key']['value']=10
>>> d
{'nested': {'key': {'value': 10}}}
Есть несколько основных способов сделать это:
- Использовать рекурсивный словарь по умолчанию
- Используйте хук
__missing__
для возврата вложенной структуры
ОК -- легко.
Теперь предположим, что я хочу вернуть значение по умолчанию из словаря с отсутствующим ключом. Еще раз, несколько способов сделать это:
- Для невложенного пути вы можете использовать хук
__missing__
- try/except блокирует доступ к потенциально отсутствующему ключевому пути
- Используйте
{}.get(key, default)
(трудно работать с вложенным словарем), т. е. Нет версииautoviv.get(['nested']['key']['no key of this value'], default)
Две цели кажутся непримиримыми конфликтами (судя по тому, что я пытался разобраться в этом последние пару часов).
Вот вопрос:
Предположим, я хочу иметь Autovivifying dict, который 1) создает вложенную структуру для d['arbitrary']['nested']['path']
; И 2) возвращает значение по умолчанию из несуществующего произвольного вложения без переноса его в try/except?
Вот проблемы:
- Вызов
d['nested']['key']['no key of this value']
эквивалентен(d['nested'])['key']['no key of this value']
. Переопределение__getitem__
не работает без возврата объекта, который ТАКЖЕ переопределяет__getitem__
. - Оба метода создания Autovivifier создадут запись в словаре, если вы проверите существование этого пути. то есть я не хочу, чтобы
if d['p1']['sp2']['etc.']
создавал весь этот путь, если вы просто протестируете его с помощьюif
.
Как я могу предоставить dict в Python, который будет:
- Создать путь доступа типа
d['p1']['p2'][etc]=val
(Автовивикация); - НЕ создавайте тот же путь, если вы проверяете его существование;
- Вернуть значение по умолчанию (например,
{}.get(key, default)
) без переноса в try/except - Мне не нужен ПОЛНЫЙ набор операций dict. На самом деле только
d=['nested']['key']['value']=val
иd['nested']['key']['no key of this value']
равны значению по умолчанию. Я бы предпочел, чтобы тестированиеd['nested']['key']['no key of this value']
не создавало его, но согласился бы с этим.
get
, которое вы хотите сделать? - person BrenBarn   schedule 30.06.2014animals={'amphibian':{'Bufoides':['Mawblang toad','Khasi Hills toad'], more amphibians...}, 'Insects':{'Ants':{'Acanthognathus'}[list of Acanthognathus]}}
, где разные записи могут вкладываться глубже, чем другие ... Также - любопытство! - person dawg   schedule 30.06.2014Return a default value (like {}.get(key, default)) without wrapping in try/except
? Если это так, я не видел рационального случая, когда я мог бы сделатьval=autoviv.get(['nested']['key']['no key of this value'], default)
{}.get не поддерживает рекурсию... - person dawg   schedule 30.06.2014[]
с помощьюget
. Возможно, вы могли бы получить приближение, используя что-то вродеget(['nested', 'key', 'no key'], default)
, где вы указываете последовательность ключей. - person BrenBarn   schedule 30.06.2014{}.get()
для работы; Я использую это как аналогию. - person dawg   schedule 30.06.2014d['one']['two']['three']
и возвращать значение по умолчанию без создания промежуточных объектов, или вам просто нужно иметь возможность вызыватьd.get(['one', 'two', 'three'], default)
? - person BrenBarn   schedule 30.06.2014