Методы словарей и операции над словарями в Python

У класса dict есть классовый метод fromkeys(iterable[, value]), с помощью которого создается новый словарь, ключи которого берутся из переданного в метод итерируемого объекта. Значениями всех ключей по-умолчанию является None или передаваемое вторым аргументом значение.

letters = 'aeiyou'
nums = [5, 8, 9, 3]
words = ('cat', 'dog', 'pig')

dl = dict.fromkeys(letters, 0)
dn = dict.fromkeys(nums)
dw = dn.fromkeys(words, 'gray')

print(dl)
print(dn)
print(dw)
{'a': 0, 'e': 0, 'i': 0, 'y': 0, 'o': 0, 'u': 0}
{5: None, 8: None, 9: None, 3: None}
{'cat': 'gray', 'dog': 'gray', 'pig': 'gray'}

Методы экземпляра словаря keys(), values(), items() возвращают особые типы объектов - dictionary view objects - объекты просмотра словаря. Эти объекты являются итерируемыми.

d = {'cat': 5, 'dog': 3, 'pig': 1}

dk = d.keys()
dv = d.values()
di = d.items()

print(dk)
print(dv)
print(di)

for k, v in di:
    print(k, '=', v)

print(list(dk))
print(tuple(dv))
dict_keys(['cat', 'dog', 'pig'])
dict_values([5, 3, 1])
dict_items([('cat', 5), ('dog', 3), ('pig', 1)])
cat = 5
dog = 3
pig = 1
['cat', 'dog', 'pig']
(5, 3, 1)

Важной особенностью экземпляров просмотра словаря является то, что они остаются "связанными" со своим словарем. Поэтому любые изменения последнего отражаются в этих объектах.

d = {'cat': 5, 'dog': 3, 'pig': 1}

di = d.items()
dv = d.values()
print(list(di))
print(sum(list(dv)))

d['cow'] = 1
d['pig'] += 1

print(list(di))
print(sum(list(dv)))
[('cat', 5), ('dog', 3), ('pig', 1)]
9
[('cat', 5), ('dog', 3), ('pig', 2), ('cow', 1)]
11

Если подобная связь не требуется, то список всех ключей словаря может быть удобнее получать с помощью встроенной функции list(iterable=()).

>>> d = {'cat': 5, 'dog': 3, 'pig': 1}
>>> k = list(d)
>>> k
['cat', 'dog', 'pig']
>>> d['cow'] = 1
>>> k
['cat', 'dog', 'pig']

Если требуется очистить содержимое словаря без удаления самого словаря, следует использовать метод clear().

d = {'cat': 5, 'dog': 3, 'pig': 1}

print(d)
print('Number of entries:', len(d))

d.clear()

print(d)
print('Number of entries:', len(d))
{'cat': 5, 'dog': 3, 'pig': 1}
Number of entries: 3
{}
Number of entries: 0

Просто удалить любую запись словаря, обращаясь к ней по ключу, можно с помощью оператора del, который в классе dict перегружается методом __delitem__(self, key). Если записи с указанным ключом нет, будет выбрашено исключение KeyError.

>>> a = dict(cat=3, dog=5, pig=1)
>>> a
{'cat': 3, 'dog': 5, 'pig': 1}
>>> del a['cat']
>>> a.__delitem__('pig')
>>> a
{'dog': 5}
>>> del a['cow']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'cow'

В отличие от del метод pop(key[, default]) не только удаляет запись из словаря по ключу, но и возвращает значение этой записи. Если переданного методу ключа нет в словаре, то в качестве значения возвращается default, если он был указан, или выбрасывается KeyError.

d = {'cat': 5, 'dog': 3, 'pig': 1}

s = sum(list(d.values()))
print(s)  # 9

s -= d.pop('dog')
print(s)  # 6

s -= d.pop('cow', 0)
print(s)  # 6

s -= d.pop('pig', 0)
print(s)  # 5

Метод popitem() не принимает аргументов, удаляет из словаря последнюю запись, возвращает ее в виде кортежа, в котором первый элемент представляет собой ключ, второй - значение. Вызов метода на пустой словарь приводит к выбросу KeyError.

d = {'cat': 5, 'dog': 3, 'pig': 1}

while len(d) != 0:
    print(d.popitem())
('pig', 1)
('dog', 3)
('cat', 5)

Метод get(key, default=None) возвращает значение указанного ключа, также как и обычное получение из словаря значения по ключу через квадратные скобки. Однако данный метод никогда не возбуждает KeyError и поэтому может быть предпочтительным в ряде случаев. Значение default возвращается, когда ключа нет в словаре. Вместо None можно указать свое значение.

d = {'cat': 5, 'dog': 3, 'pig': 1}

for i in range(4):
    print(d.get(input('Pet: ')))
Pet: dog
3
Pet: cow
None
Pet: pig
1
Pet: rabbit
None

По аналогии с этим при добавлении записи в словарь вместо нотации d[key] = value можно использовать метод setdefault(key, default=None). Его отличительной особенностью является то, что если запись с таким ключом уже есть в словаре, ее значение не будет перезаписано. При этом метод возвращает значение ключа, по которому можно оценить, была ли добавлена новая запись, или она уже ранее присутствовала в словаре.

d = {'cat': 5, 'dog': 3, 'pig': 1}

n = d.setdefault('cow', 1)
print(n)

n = d.setdefault('dog', 1)
print(n)

print(d)
1
3
{'cat': 5, 'dog': 3, 'pig': 1, 'cow': 1}

Наличие записи в словаре можно проверить с помощью оператора in.

d = {'cat': 5, 'dog': 3, 'pig': 1}

print('cat' in d)  # True
print('cat' not in d)  # False

print('cow' in d)  # False
print('cow' not in d)  # True

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

>>> first = {'a': 3, 'b': 5}
>>> second = first
>>> third = first.copy()
>>>
>>> second['c'] = 4
>>>
>>> first
{'a': 3, 'b': 5, 'c': 4}
>>> second
{'a': 3, 'b': 5, 'c': 4}
>>> third
{'a': 3, 'b': 5}
>>>
>>> id(first) == id(second)
True
>>> id(first) == id(third)
False

При этом метод copy() выполняет поверхностное копирование. Это значит, что если какое-либо значение словаря является изменяемым типом, то его изменение в одном словаре отразится в другом.

>>> first = {'bread': [4, 28.5], 'milk': 6}
>>> second = first.copy()
>>>
>>> first['bread'][1] += 0.75
>>> first['milk'] = [6, 58]
>>>
>>> first
{'bread': [4, 29.25], 'milk': [6, 58]}
>>> second
{'bread': [4, 29.25], 'milk': 6}

С помощью метода update([other]) можно объединить два словаря в один или, используя итерируемый объект, добавить в словарь новые записи или обновить значения существующих. При совпадении ключей значения словаря, к которому применяется метод, перезаписываются на новые.

d = {'cat': 5, 'dog': 3}
print(d)

d.update({'dog': 1, 'pig': 2})
d.update([('rabbit', 4), ('sheep', 2)])
d.update(hen=8, cat=3, pig=5)
print(d)
{'cat': 5, 'dog': 3}
{'cat': 3, 'dog': 1, 'pig': 5, 'rabbit': 4, 'sheep': 2, 'hen': 8}