TL; DR
Как я могу получить superkeys быть autovivified в Словаре Python при присвоении значений подразделов, без также получать их autovivified при проверке подразделы?Как реализовать автовивитацию для вложенного словаря ТОЛЬКО при назначении значений?
фона: Обычно в Python, устанавливая значения в гнездовой словаря требует вручную обеспечения того, чтобы ключи более высокого уровня существуют перед назначением их суб-ключей. То есть,
my_dict[1][2] = 3
не будет надежно работать, как предполагалось, не первый делать что-то вроде
if 1 not in my_dict:
my_dict[1] = {}
Теперь можно настроить вид autovivification, сделав my_dict
экземпляром класса, который переопределяет __missing__
, как показано, например в https://stackoverflow.com/a/19829714/6670909.
Вопрос: Тем не менее, это решение молча автогенерирует ключи более высокого уровня, если вы проверяете наличие под-ключа в таком вложенном dict. Это приводит к следующей неудовлетворенности:
>>> vd = Vividict()
>>> 1 in vd
False
>>> 2 in vd[1]
False
>>> 1 in vd
True
Как я могу избежать этого вводящего в заблуждение результата? В Perl, кстати, я могу получить желаемое поведение, делая
no autovivification qw/exists/;
И в основном я хотел бы повторить это поведение в Python, если это возможно.
Вы не можете. Нет никакой разницы между доступом 'vd [1]', потому что вы назначаете ему и потому, что видите, что он содержит, насколько это касается 'vd'. Также это не вводящий в заблуждение результат - после того, как вы посмотрели в 'vd [1]', '1' ** - **' in vd'. – jonrsharpe
Право: я надеюсь, что может быть какой-то способ сделать это, например, путем создания класса для вложенных словарей, который ** ** чувствителен к различию между (а) получением элемента просто для того, чтобы проверить существование подпункта и (b) получение элемента в контексте попытки установить значение подпункта. Я думаю, что различие должно было бы быть сделано, фактически, перед неявным вызовом '__getitem__'. –
Нет. '__getitem__' не знает, что делается с результатом при вызове. Раньше не было крючка. Например, вам нужно будет предоставить свой собственный метод, а не использовать 'x in y' -' y.contains (x) ', например. – jonrsharpe