Словари (dict, dictionary) в Python

Введение

Словарь — это пример хранилища значений ключей, также известного как Mapping в Python. Он позволяет хранить и извлекать элементы, ссылаясь на ключ. Так как словари ссылаются по ключу, в них быстро работает поиск, поскольку они в основном используются для ссылки на элементы по ключу и они не сортируются.



Примеры

  • Доступ к значениям словаря

    dictionary = {"Hello": 1234, "World": 5678}
    print(dictionary["Hello"])

    

    Приведённый выше код выведет 1234.

    

    Строка "Hello" в этом примере называется ключом. Он используется для поиска значения в словаре, помещая ключ в квадратные скобки.

    

    Число 1234 видно после соответствующего двоеточия в словаре. Это значение, на которое ведёт "Hello" в словаре.

    

    Поиск значения, с несуществующим ключом, вызовет исключение KeyError, остановив выполнение. Если мы хотим получить доступ к значению, без риска получить KeyError, мы можем использовать метод dictionary.get. По умолчанию, если ключ не существует, метод вернет None. Мы можем передать ему второе значение, чтобы вернуть вместо None в случае неудачного поиска.

    

    w = dictionary.get("whatever")

    x = dictionary.get("whatever", "nuh-uh")

    

    В этом примере w получит значение None, а x получит значение "nuh-uh".

    

  • Конструктор dict()

    Конструктор dict() можно использовать для создания словарей из именованных аргументов или из одной итерируемой пары ключ-значение или из одного словаря и именованного аргумента.

    dict(a=1, b=2, c=3) # {'a': 1, 'b': 2, 'c': 3}
    dict([('d', 4), ('e', 5), ('f', 6)]) # {'d': 4, 'e': 5, 'f': 6}
    dict([('a', 1)], b=2, c=3) # {'a': 1, 'b': 2, 'c': 3}
    dict({'a' : 1, 'b' : 2}, c=3) # {'a': 1, 'b': 2, 'c': 3}

    

  • Как избегать исключений KeyError

    Распространённая ошибка при использовании словарей — доступ к несуществующему ключу. Это обычно приводит к исключению KeyError:

    mydict = {}
    mydict['not there']
    
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    KeyError: 'not there'

    

    Один из способов избежать KeyError — использовать метод dict.get, который позволяет вам указать значение по умолчанию, которое будет возвращать в случае отсутствия ключа.

    value = mydict.get(key, default_value)

    

    Возвращает mydict[key], если он существует, но в противном случае возвращает default_value. Обратите внимание, что это не добавляет key к mydict. Поэтому, если вы хотите сохранить эту пару ключ-значение, вы должны использовать mydict.setdefault(key, default_value), который хранит пару ключ-значение.

    mydict = {}
    print(mydict)
    # {}
    print(mydict.get("foo", "bar"))
    # bar
    print(mydict)
    # {}
    print(mydict.setdefault("foo", "bar"))
    # bar
    print(mydict)
    # {'foo': 'bar'}

    

    Другой способ избавиться от ошибки — перехватить исключение

    try:
    value = mydict[key]
    except KeyError:
    value = default_value

    

    Вы также можете проверить, есть ли ключ словаре:

    if key in mydict:
    value = mydict[key]
    else:
    value = default_value

    

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

    

    В качестве другого вариант можно использовать подкласс dict collection.defaultdict, который имеет значение default_factory для создания новых записей в dict при получении new_key.

    

  • Доступ к ключам и значениям

    При работе со словарями часто требуется получить доступ ко всем ключам и значениям в словаре, в цикле for, в генераторе списка или просто в виде простого списка.

    

    Словарь будет таким:

    mydict = {
    'a': '1',
    'b': '2'
    }

    

    Вы можете получить список ключей, используя метод keys или функцию dict_keys:

    print(mydict.keys())
    dict_keys(['b', 'a'])

    

    Если вместо этого вы хотите получить список значений, используйте метод values или функцию dict_values:

    print(mydict.values())
    dict_values(['2', '1'])

    

    Если вы хотите работать как с ключом, так и с соответствующим значением, вы можете использовать метод items или функцию dict_ items:

    print(mydict.items())
    dict_items([('b', '2'), ('a', '1')])

    

    Примечание. Поскольку словари не отсортированы, keys, values и items не имеют порядка сортировки. Используйте функции sort, sorted или класс OrderedDict, если вам важен порядок, в котором возвращают эти методы.

  • Введение в словарь

    Создание словаря

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

    

    С помощью литерала

    d = {} # пустой словарь
    d = {"key": "value"} # словарь с начальными значениями
    
    # Распаковка одного или нескольких словарей литералом
    d = {**otherdict} # создаёт копию otherdict
    d = {**otherdict, **yetanotherdict} # создает копию otherdict и butanotherdict

    С помощью генератора словаря

    d = {k:v for k,v in [('key', 'value',)]}

    

    

    Через встроенный класс dict()

    d = dict() # пустой словарь
    d = dict(key='value') #точные именованные аргументы
    d = dict([('key', 'value')]) # передаёт в список пар key/value
    d = dict(**otherdict) # делает мелкую копию another dict (возможно только если все ключи являются строками!)

    

    Модификация словаря

    Чтобы добавить элементы в словарь нужно создать новый ключ со значением:

    d['newkey'] = 42

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

    d['new_list'] = [1, 2, 3]
    d['new_dict'] = {'nested_dict': 1}

    Чтобы удалить элемент, нужно удалить ключ из словаря:

    del d['newkey']

    

  • Словари со значениями по умолчанию

    Доступно в стандартной библиотеке как defaultdict

    from collections import defaultdict
    
    d = defaultdict(int)
    d['key'] # 0
    d['key'] = 5
    d['key'] # 5
    
    d = defaultdict(lambda: 'empty')
    d['key'] # 'empty'
    d['key'] = 'full'
    d['key'] # 'full'

    

    В качестве альтернативы, если вы используете встроенный класс dict, использование dict.setdefault() позволит создать значение по умолчанию всегда, когда вы обращаетесь к отсутствующему ранее ключу:

    >>> d = {}
    {}
    >>> d.setdefault('Another_key', []).append("This worked!")
    >>> d
    {'Another_key': ['This worked!']}

    

    Если вам нужно добавить много значений, dict.setdefault() будет создавать новый экземпляр начального значения (в этом примере a[]) каждый раз, когда оно вызывается, создавая лишнюю нагрузку.

  • Как создать упорядоченный словарь

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

    

    Используйте OrderedDict из модуля collections. Он будет возвращать элементы словаря в исходном порядке когда переборка завершится:

    from collections import OrderedDict
    
    d = OrderedDict()
    d['first'] = 1
    d['second'] = 2
    d['third'] = 3
    d['last'] = 4
    
    # Outputs "first 1", "second 2", "third 3", "last 4"
    for key in d:
    print(key, d[key])
  • Распаковка словарей с помощью оператора **

    Вы можете использовать оператор распаковки именованного аргумента слова ** для доставки пар ключ-значение в словаре в аргументы функции. Упрощенный пример из официальной документации:

    >>>
    >>> def parrot(voltage, state, action):
    ... print("This parrot wouldn't", action, end=' ')
    ... print("if you put", voltage, "volts through it.", end=' ')
    ... print("E's", state, "!")
    ...
    >>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
    >>> parrot(**d)
    This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !

    

    Начиная с Python 3.5 вы также можете использовать этот синтаксис для объединения произвольного числа объектов [dict].

    >>> fish = {'name': "Nemo", 'hands': "fins", 'special': "gills"}
    >>> dog = {'name': "Clifford", 'hands': "paws", 'color': "red"}
    >>> fishdog = {**fish, **dog}
    >>> fishdog
    
    {'hands': 'paws', 'color': 'red', 'name': 'Clifford', 'special': 'gills'}

    

    Этот пример показывает, что дубликаты ключей соответствуют последнему значению (например, «Клиффорд» переопределяет «Немо»).

    

  • Объединений словарей

    Рассмотрим разные словари:

    fish = {'name': "Nemo", 'hands': "fins", 'special': "gills"}
    dog = {'name': "Clifford", 'hands': "paws", 'color': "red"}

    

    Python 3.5+

    fishdog = {**fish, **dog} # {'hands': 'paws', 'color': 'red', 'name': 'Clifford', 'special': 'gills'}

    

    В этом примере, дубликаты ключей соответствуют последнему значению (например, «Клиффорд» переопределяет «Немо»).

    

    Python 3.3+

    from collections import ChainMap
    dict(ChainMap(fish, dog)) # {'hands': 'fins', 'color': 'red', 'special': 'gills', 'name': 'Nemo'}

    

    Здесь первостепенное значение отдаётся кокретному ключу, а не последнему («Клиффорд» выбрасывается в пользу «Немо»).

    

    Python 2.x, 3.x

    >>> from itertools import chain
    >>> dict(chain(fish.items(), dog.items()))
    {'hands': 'paws', 'color': 'red', 'name': 'Clifford', 'special': 'gills'}

    

    Здесь используется последнее значение, как и в методе слияния [**] («Клиффорд» переопределяет «Немо»).

    fish.update(dog)
    fish # {'color': 'red', 'hands': 'paws', 'name': 'Clifford', 'special': 'gills'}
  • Замыкающая запятая

    Также как в списках или кортежах, можно добавлять замыкающую запятую в своем словаре.

    role = {"By day": "A typical programmer", "By night": "Still a typical programmer", }

    PEP 8 требует, чтобы вы оставляли пробел между замыкающей запятой и закрывающей скобкой.

    

  • Все комбинации значений словаря

    options = {

    "x": ["a", "b"],

    "y": [10, 20, 30]

    }

    

    Дан словарь в примере выше, где есть список, представляющий набор значений для поиска соответствующего ключа. Предположим, вы хотите найти "x"="a" с "y"=10, затем "x"="a" с "y"=10 и т. д., пока вы не переберете все возможные комбинации.

    

    Вы можете создать список, который возвращает все такие комбинации значений, используя следующий код.

    import itertools
    
    options = {
    "x": ["a", "b"],
    "y": [10, 20, 30]
    }
    
    keys = options.keys()
    values = (options[key] for key in keys)
    combinations = [dict(zip(keys, combination)) for combination in itertools.product(*values)]
    print combinations

    

    Это дает нам следующий список, хранящийся в переменной combinations:

    [{'x': 'a', 'y': 10},
    {'x': 'b', 'y': 10},
    {'x': 'a', 'y': 20},
    {'x': 'b', 'y': 20},
    {'x': 'a', 'y': 30},
    {'x': 'b', 'y': 30}]

    

  • Перебор словаря

    Если вы используете словарь в качестве итератора (например, в операторе for), он перемещает ключи в словаре. Например:

    d = {'a': 1, 'b': 2, 'c':3}
    for key in d:
    print(key, d[key])
    # c 3
    # b 2
    # a 1

    

    Работает таким же образом в генераторах:

    print([key for key in d])
    # ['c', 'b', 'a']

    

    Метод items() можно использовать для одновременного зацикливания ключа и значения:

    for key, value in d.items():
    print(key, value)
    # c 3
    # b 2
    # a 1

    

    Метод values() можно использовать для перебора только значений:

    for key, value in d.values():
    print(key, value)
    # 3
    # 2
    # 1
  • Создание словаря

    Правила создания словаря:

    • каждый ключ должен быть уникальным (иначе он будет переопределен);
    • каждый ключ должен быть хэшируемым (для хеширования применяется функция hash) в противном случае возникнет исключение TypeError;
    • для ключей нет определённого порядка.
    • 
    #Создание и заполнение значениями
    stock = {'eggs': 5, 'milk': 2}
    
    #Создание пустого словаря
    dictionary = {}
    
    #И заполнение его позднее
    dictionary['eggs'] = 5
    dictionary['milk'] = 2
    
    #Значения также могут быть списками
    mydict = {'a': [1, 2, 3], 'b': ['one', 'two', 'three']}
    
    #Используй метод list.append() чтобы добавить новый элемент в список значений
    mydict['a'].append(4) # => {'a': [1, 2, 3, 4], 'b': ['one', 'two', 'three']}
    mydict['b'].append('four') # => {'a': [1, 2, 3, 4], 'b': ['one', 'two', 'three', 'four']}
    
    # Мы также можем создать словарь, используя список из двух элементов
    iterable = [('eggs', 5), ('milk', 2)]
    dictionary = dict(iterables)
    
    # Или используя именованный аргумент:
    dictionary = dict(eggs=5, milk=2)
    
    #Другой способ использования dict.fromkeys:
    dictionary = dict.fromkeys((milk, eggs)) # => {'milk': None, 'eggs': None}
    dictionary = dict.fromkeys((milk, eggs), (2, 5)) # => {'milk': 2, 'eggs': 5}

    

  • Примеры словарей

    Словари сопоставляют ключи со значениями

    car = {}
    car["wheels"] = 4
    car["color"] = "Red"
    car["model"] = "Corvette"

    Доступ к значениям словаря осуществляется по их ключам

    print "Little " + car["color"] + " " + car["model"] + "!"
    # Этот код напечатает "Little Red Corvette!"

    Словари также могут быть созданы в стиле JSON:

    car = {"wheels": 4, "color": "Red", "model": "Corvette"}

    Значения словаря могут быть перебраны:

    for key in car:
    print key + ": " + car[key]
    
    # wheels: 4
    # color: Red
    # model: Corvette

    

Синтаксис

mydict = {}
mydict[k] = value
value = mydict[k]
value = mydict.get(k)
value = mydict.get(k, "default_value")

Параметры

Примечания

Что следует помнить при использовании словаря:

– каждый ключ должен быть уникальным (иначе он будет переопределен);

– каждый ключ должен быть хэшируемым (для хеширования применяется функция hash) в противном случае возникнет исключение TypeError;

– для ключей нет определённого порядка.