Добавление collections.defaultdict
в Python 2.5 значительно уменьшил потребность в dict
setdefault
метод. Этот вопрос для нашего коллективного образования:
setdefault
все еще полезный для, сегодня в Python 2.6/2.7?setdefault
были заменены с collections.defaultdict
? Можно сказать, что defaultdict
полезен для настроек по умолчанию перед заполнением dict , а setdefault
полезен для установки значений по умолчанию во время или после заполнения dict .
Вероятно, наиболее распространенный вариант использования: Группировка элементов (в несортированных данных, иначе используйте itertools.groupby
)
# really verbose
new = {}
for (key, value) in data:
if key in new:
new[key].append( value )
else:
new[key] = [value]
# easy with setdefault
new = {}
for (key, value) in data:
group = new.setdefault(key, []) # key might exist already
group.append( value )
# even simpler with defaultdict
new = defaultdict(list)
for (key, value) in data:
new[key].append( value ) # all keys have a default already
Иногда вы хотите убедиться, что определенные ключи существуют после создания dict. defaultdict
не работает в этом случае, потому что он создает ключи только при явном доступе. Думаю, вы используете что-то в стиле HTTP со многими заголовками - некоторые из них необязательны, но вам нужны значения по умолчанию для них:
headers = parse_headers( msg ) # parse the message, get a dict
# now add all the optional headers
for headername, defaultvalue in optional_headers:
headers.setdefault( headername, defaultvalue )
Я обычно использую setdefault
для словарных аргументов аргументов, например, в этой функции:
def notify(self, level, *pargs, **kwargs):
kwargs.setdefault("persist", level >= DANGER)
self.__defcon.set(level, **kwargs)
try:
kwargs.setdefault("name", self.client.player_entity().name)
except pytibia.PlayerEntityNotFound:
pass
return _notify(level, *pargs, **kwargs)
Он отлично подходит для настройки аргументов в оболочках вокруг функций, которые принимают аргументы ключевого слова.
Теоретически, setdefault
все равно будет удобен, если вы иногда хотите установить значение по умолчанию, а иногда нет. В реальной жизни я не встречал такого варианта использования.
Однако интересный вариант использования возникает из стандартной библиотеки (Python 2.6, _threadinglocal.py):
>>> mydata = local()
>>> mydata.__dict__
{'number': 42}
>>> mydata.__dict__.setdefault('widgets', [])
[]
>>> mydata.widgets
[]
Я бы сказал, что использование __ dict __. Setdefault
является довольно полезным случаем.
Правка : Как оказалось, это единственный пример в стандартной библиотеке, и он находится в комментарии. Так что, возможно, этого недостаточно, чтобы оправдать существование setdefault
. Тем не менее, вот объяснение:
Объекты хранят свои атрибуты в атрибуте __ dict __
. Так получилось, что атрибут __ dict __
доступен для записи в любое время после создания объекта. Это также словарь, а не defaultdict
. Для объектов в общем случае неразумно иметь __ dict __
в качестве defaultdict
, потому что в этом случае каждый объект будет иметь все допустимые идентификаторы в качестве атрибутов. Поэтому я не могу предвидеть каких-либо изменений в объектах Python, избавляющихся от __ dict __. Setdefault
, кроме его полного удаления, если он будет сочтен бесполезным.