Я использую defaultdict(set)
для заполнения внутреннего сопоставления в очень большой структуре данных. После заполнения вся структура (включая сопоставление) становится доступной для клиентского кода. В этот момент я не хочу, чтобы кто-либо модифицировал сопоставление.
И никто не делает этого намеренно. Но иногда клиентский код может случайно ссылаться на несуществующий элемент. В этот момент обычный словарь поднял бы KeyError
, но поскольку отображение равно defaultdict
, он просто создает новый элемент (пустой набор) в этом ключе. Это довольно сложно уловить, так как все происходит тихо. Но мне нужно убедиться, что этого не произойдет (семантика на самом деле не ломается, но отображение увеличивается до огромных размеров).
Что я должен делать? Я вижу эти варианты:
Найдите все экземпляры в текущем и будущем клиентском коде, где поиск по словарю выполняется для сопоставления, и вместо этого преобразуйте его в
mapping.get(k, {})
. Это просто ужасно."Заморозить"
defaultdict
после полной инициализации структуры данных, преобразовав ее вdict
. (Я знаю, что на самом деле это не заморожено, но я верю, что клиентский код на самом деле не пишетmapping[k] = v
.) Неэлегантно и сильно влияет на производительность.Оберните
defaultdict
интерфейсомdict
. Какой элегантный способ сделать это? Я боюсь, что удар по производительности может быть огромным (этот поиск часто используется в узких циклах).Подкласс
defaultdict
и добавьте метод, который «отключает» все функцииdefaultdict
, оставляя его вести себя как обычныйdict
. Это вариант 3 выше, но я не уверен, что он быстрее. И я не знаю, выполнимо ли это, не полагаясь на детали реализации.Используйте обычный
dict
в структуре данных, переписав весь код там, чтобы сначала проверить, есть ли элемент в словаре, и добавить его, если нет. Фигово.
dict.setdefault
... Ничего страшного - person JBernardo   schedule 20.11.2012defaultdict
, это то, что он переопределяет__getitem__
для добавления элемента, если это необходимо. Может быть, он делает это с помощью методаsetdefault
, может быть, он реализует ту же логику напрямую, даже не вызываяsetdefault
. Не полагаясь на детали реализации, я не могу ничего предположить, не так ли? - person max   schedule 20.11.2012dict
defaultdict
, чтобы продиктовать это. - person inspectorG4dget   schedule 20.11.2012defaultdict
, не так ли? (Не то чтобы я не согласен, просто хочу понять логику.) - person max   schedule 20.11.2012dict
) слишком дорого. - person max   schedule 20.11.2012dict.setdefault
реализован на C и делает именно то, что делаетdefaultdict.__getitem__
. Разве это не должно быть одинаково быстро? - person max   schedule 20.11.2012