Программирование на Python: Часть 4. Словари

Словари наряду со списками являются наиболее простыми, гибкими и мощными коллекционными типами. Словарь, как и список, является изменяемым (mutable) типом данных, хотя и содержит неизменяемые ключи и может неограниченно расти.

После списков словарь является самым гибким встроенным типом. Если список — это упорядоченная коллекция, то словарь — неупорядоченная. Основные особенности словарей:

  1. Доступ осуществляется по ключу, а не по индексу. По аналогии со списком, в словаре можно получить доступ к элементам в цикле по ключам.
  2. Значения словаря хранятся в неотсортированном порядке, более того, ключи могут храниться не в том порядке, в котором они добавляются.
  3. По аналогии со списками, словарь может хранить вложенные словари. Словарь может хранить в качестве значений объекты любого типа (heterogeneous). Ключ в словаре — immutable тип, может быть строкой, целым числом, float либо кортежем, состоящим из указанных типов.
  4. Словари реализованы как хеш-таблицы с быстрым доступом.
  5. Словари, так же как и списки, хранят ссылки на объекты, а не сами объекты.

Сегодня мы рассмотрим следующие темы.

  1. Что такое словарь.
  2. Функции/методы словаря.
  3. Операции со словарем.
  4. Примеры.

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

Создать словарь можно несколькими способами:

  1. Обычное выражение — оно удобно, если словарь статичен:
        D = {'name': 'mel', 'age': 45}
  2. Динамический вариант создания на лету:
        D = {}
        D['name'] = 'mel'
        D['age'] = 45
  3. С помощью функции 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)))
  4. С помощью fromkeys() — создает словарь по списку ключей с пустыми значениями:
        D = {}.fromkeys(['name', 'age'],123)
  5. С помощью конструктора:
        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.

Предыдущая статья. Следующая статья.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source, Linux
ArticleID=505647
ArticleTitle=Программирование на Python: Часть 4. Словари
publish-date=08092010