Программирование на Python: Часть 4. Словари
Серия контента:
Этот контент является частью # из серии # статей:
Этот контент является частью серии:
Следите за выходом новых статей этой серии.
После списков словарь является самым гибким встроенным типом. Если список — это упорядоченная коллекция, то словарь — неупорядоченная. Основные особенности словарей:
- Доступ осуществляется по ключу, а не по индексу. По аналогии со списком, в словаре можно получить доступ к элементам в цикле по ключам.
- Значения словаря хранятся в неотсортированном порядке, более того, ключи могут храниться не в том порядке, в котором они добавляются.
- По аналогии со списками, словарь может хранить вложенные словари. Словарь может хранить в качестве значений объекты любого типа (heterogeneous). Ключ в словаре — immutable тип, может быть строкой, целым числом, float либо кортежем, состоящим из указанных типов.
- Словари реализованы как хеш-таблицы с быстрым доступом.
- Словари, так же как и списки, хранят ссылки на объекты, а не сами объекты.
Сегодня мы рассмотрим следующие темы.
- Что такое словарь.
- Функции/методы словаря.
- Операции со словарем.
- Примеры.
1. Что такое словарь
Словарь (dictionary) — это ассоциативный массив или хеш. Это неупорядоченное множество пар ключ: значение с требованием уникальности ключей. Пара фигурных скобок {}
создает пустой словарь. В отличие от последовательностей, доступ к элементам словаря производится по ключу, а не по индексу, ключ может быть любого типа, ключ не допускает изменений.
Основные операции над словарем — сохранение с заданным ключом и извлечение по нему значения. Также можно удалить пару key: value
с помощью инструкции del
.
Метод keys()
для словаря возвращает список всех используемых ключей в произвольном порядке; для сортировки списка нужно применить метод sort()
. Для определения наличия определенного ключа есть метод has_key()
, который в версии 3.0 успеет устареть — вместо него есть оператор in
. Добавление нового объекта в словарь не требует предварительных проверок: если ранее ключу уже соответствовало некоторое значение, оно будет перезаписано.
Пример — словарь в качестве телефонного справочника:
>>> dic = {'vanya' : 23323223, 'smith' : 32232332} >>> dic['fedya'] = 33332222 >>> dic {'vanya': 23323223, 'fedya': 33332222, 'smith': 32232332} >>> dic['smith'] 32232332 >>> del dic['vanya'] >>> dic {'fedya': 33332222, 'smith': 32232332} >>> dic.keys() ['fedya', 'smith'] >>> dic.has_key('fedya') True
Создать словарь можно несколькими способами:
- Обычное выражение — оно удобно, если словарь статичен:
D = {'name': 'mel', 'age': 45}
- Динамический вариант создания на лету:
D = {} D['name'] = 'mel' D['age'] = 45
- С помощью функции dict() — ключи при этом должны быть строками. С помощью этой функции можно избавить себя от обязательного условия заключать ключ в кавычки. В примере приведены четыре варианта создания одного и того же словаря:
d1 = dict(id=1948, name="Washer", size=3) d2 = dict({"id": 1948, "name": "Washer", "size": 3}) d3 = dict([("id", 1948), ("name", "Washer"), ("size", 3)]) d4 = dict(zip(("id", "name", "size"), (1948, "Washer", 3)))
- С помощью
fromkeys()
— создает словарь по списку ключей с пустыми значениями:D = {}.fromkeys(['name', 'age'],123)
- С помощью конструктора:
d = dict((x, x**2) for x in xrange(5))
2. Функции/методы словаря
dict()
— создание словаря;
len()
— возвращает число пар;
clear()
— удаляет все значения из словаря;
copy()
— создает псевдокопию словаря;
deepcopy()
— создает полную копию словаря;
fromkeys()
— создание словаря;
get()
— получить значение по ключу;
has_key()
— проверка значения по ключу;
items()
— возвращает список значений;
iteriyems()
— возвращает итератор;
keys()
— возвращает список ключей;
iterkeys()
— возвращает итератор ключей;
pop()
— извлекает значение по ключу;
popitem()
— извлекает произвольное значение;
update()
— изменяет словарь;
values()
— возвращает список значений;
itervalues()
— возвращает итератор на список значений.
in
— оператор, проверяет наличие значения по ключу;
del
— оператор, удаляет пару по ключу;
dict()
— конструирует словарь с помощью последовательности.
Например, создать словарь с помощью списка кортежей:
>>> items = [('name','sveta'),('age',20)] >>> d = dict(items) >>> d {'age': 20, 'name': 'sveta'} >>> len(d) 2
in()
— оператор проверки вхождения.
Пример: база данных может быть заполнена в виде словаря.
Проверить наличие в базе данных телефона по имени:
people = {'Alice': {'phone': '2341', 'addr': 'Foo drive 23' }, 'Beth': {'phone': '9102', 'addr': 'Bar street 42'}} name = 'Alice' key = 'phone' if name in people: print "%s phone is %s" % (name, people[name][key]) >>> Alice phone is 2341 copy()
Пример создания копии словаря:
>>> x = {"user":'admin','attr':[1,2,3]} >>> y = x.copy() >>> y {'user': 'admin', 'attr': [1, 2, 3]}
Метод copy()
не делает полного копирования: если мы, например, сделаем операцию:
>>> x['attr'].remove(1)
то с удивлением обнаружим, что удаление атрибута произойдет также и в копии.
Чтобы этого не произошло, нужно использовать метод deepcopy()
.
>>> from copy import deepcopy >>> y = x.deepcopy()
fromkeys()
— создает словарь по заданным ключам с пустыми значениями:
>>> {}.fromkeys(['name', 'age']) {'age': None, 'name': None}
Можно все значения заполнить по умолчанию:
>>> {}.fromkeys(['name', 'age'],123) {'age': 123, 'name': 123}
get()
— получает значение по ключу, в случае отсутствия дает None
:
>>> d = {} >>> print d.get('name') None
has_key()
— проверяет, есть ли в словаре значение по данному ключу:
>>> d = {} >>> d.has_key('name') False
items()
— возвращает список значений:
for key, value in d.items(): print(key, value)
iteriyems()
— возвращает итератор — выдает тот же результат:
>>> for k, v in d.iteritems(): ... print k, v
keys()
— возвращает список ключей;
iterkeys()
— возвращает итератор ключей:
>>> d.keys() ['url', 'title'] >>> d.iterkeys() <dictionary-keyiterator object at 0xb7c4dd00>
pop()
— извлекает значение по ключу с последующим удалением:
>>> d.pop('title') >>> d {'url': 'http://www.python.org'}
popitem()
— извлекает произвольное значение с последующим удалением:
>>> d = {'title': 'Python Web Site', 'url': 'http://www.python.org', 'www': 'python'} >>> d.popitem() >>> d {'www': 'python', 'title': 'Python Web Site'}
update()
— изменяет значение по ключу:
>>> d2 = {'www':'python.org'} >>> d.update(d2) >>> d {'www': 'python.org', 'title': 'Python Web Site'}
values()
— возвращает список значений:
>>> d={} >>> d[1]=1 >>> d[2]=2 >>> d[3]=3 >>> d {1: 1, 2: 2, 3: 3} >>> d.values() [1, 2, 3]
del
— оператор удаляет пару ключ: значение по ключу:
>>> del d[2] >>> d {1: 1, 3: 3}
3. Операции
Поскольку словари представляют собой мапы (map), а не последовательности, к ним нельзя применить конкатенацию или срезы.
К словарям можно применять стандартные операторы сравнения:
<, <=, ==, !=, >=, >
Для того чтобы сделать проход по ключам словаря, используем for:
>>> table = {'Python': 'Guido van Rossum', ... 'Perl': 'Larry Wall', ... 'Tcl': 'John Ousterhout' } >>> for lang in table: ... print(lang, table[lang]) .. >>> Tcl John Ousterhout >>> Python Guido van Rossum >>> Perl Larry Wall
Словари хорошо подходят для хранения многомерных массивов или матриц:
>>> Matrix = {} >>> Matrix[(2, 3, 4)] = 88 >>> Matrix[(7, 8, 9)] = 99 >>> >>> X = 2; Y = 3; Z = 4 >>> Matrix[(X, Y, Z)] 88 >>> Matrix {(2, 3, 4): 88, (7, 8, 9): 99}
С помощью словарей можно хранить структурированную информацию в виде записей:
>>> man = {'name': 'Serg', ... 'jobs': ['programmer', 'writer'], ... 'web': 'www.iakovlev.org', ... 'home': {'city': 'Moscow', 'zip':129000}} >>> man['name'] Serg >>> man['jobs'][1] 'writer'
4. Примеры
Пример 1. Подсчитаем, сколько раз в строке встречается каждый символ:
def histogram(s): d = dict() for c in s: if c not in d:d[c] = 1 else:d[c] += 1 return d hist = histogram('how many times') >>> {'a': 1,'e': 1,'i': 1,'h': 1,'m': 2,'o': 1,'n': 1,'s': 1,'t': 1,'w': 1,'y': 1}
Если нам нужно инвертировать данный словарь и в качестве ключа поставить частоту:
def invert_dict(d): inv = dict() for key in d: val = d[key] if val not in inv:inv[val] = [key] else:inv[val].append(key) return inv print invert_dict(hist) >>> {1: ['a', 'e', 'i', 'h', 'o', 'n', 's', 't', 'w', 'y'], 2: [' ', 'm']}
Пример 2. Подсчитать частоту повторов каждого уникального слова в файле:
import string import sys words = {} strip = string.whitespace + string.punctuation + string.digits + "\"'" filename = 'file' for line in open(filename): for word in line.lower().split(): word = word.strip(strip) if len(word) > 2: words[word] = words.get(word, 0) + 1 for word in sorted(words): print("'{0}' occurs {1} times".format(word, words[word]))
Пример 3. Сортировка словаря по ключам:
author = {"php":"Rasmus Lerdorf",\ "perl":"Larry Wall",\ "tcl":"John Ousterhout",\ "awk":"Brian Kernighan",\ "java":"James Gosling",\ "parrot":"Simon Cozens",\ "python":"Guido van Rossum"} #Либо так: langs = author.keys() langs.sort() for language in langs: print language," - ",author[language] #либо так: for key in sorted(author.iterkeys()): print "%s: %s" % (key, author[key]) >>> awk - Brian Kernighan >>> java - James Gosling >>> parrot - Simon Cozens >>> perl - Larry Wall >>> php - Rasmus Lerdorf >>> python - Guido van Rossum >>> tcl - John Ousterhout
Пример 4. Как инвертировать словарь, т.е. поменять ключи со значениями:
def invert_dict_nonunique(d): newdict = {} for k, v in d.iteritems(): newdict.setdefault(v, []).append(k) return newdict d = {'child1': 'parent1','child2': 'parent1','child3': 'parent2','child4': 'parent2'} print invert_dict_nonunique(d) >>> {'parent2': ['child3', 'child4'], 'parent1': ['child1', 'child2']}
Заключение
Можно подвести итоги: словари наряду со списками являются наиболее простыми, гибкими и мощными коллекционными типами. Словарь, как и список, является изменяемым (mutable) типом данных, хотя и содержит неизменяемые ключи и может неограниченно расти. Если вам нужна коллекция с доступом по ключу — словарь подходит для этого лучше всего. Если вам нужна коллекция для хранения произвольных объектов произвольной вложенности — словарь в этом вам поможет.
Код примеров проверялся на версии питона 2.6.
Предыдущая статья. Следующая статья.
Ресурсы для скачивания
Комментарии
Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.