Содержание


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

Comments

Серия контента:

Этот контент является частью # из серии # статей:

Следите за выходом новых статей этой серии.

Этот контент является частью серии:

Следите за выходом новых статей этой серии.

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

  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.

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


Ресурсы для скачивания


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

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