На прошлом занятии

  • создание и изменение словарей
  • перебор словарей
  • пример: частотный словарь

План этого занятия

  • вложенные словари
  • dict.setdefault

Вложенные словари

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

>>> dict_of_lists = {
... 'Ксюша': ['ручка', 'ручка', 'карандаш', 'ластик',],
... 'Миша': ['ручка', 'мелок', 'линейка',],
... }

Используя такую структуру очень просто отвечать на вопросы типа: «Что в пенале у Миши?», «У кого больше всего предметов в пенале?»:

>>> print('В пенале у Миши:', ', '.join(dict_of_lists['Миша']))
В пенале у Миши: ручка, мелок, линейка
>>> max_count = -1
>>> rich_student = None
>>> for student, case in dict_of_lists.items():
...     count = len(case)
...     if count > max_count:
...         rich_student = student
...         max_count = count
>>> print('Самый набитый пенал у ученика по имени', rich_student)
Самый набитый пенал у ученика по имени Ксюша

Если нам не важен порядок предметов, уложенных в пинал, но важно уметь быстро и удобно получить число предметов данного типа, то удобнее представить пенал в виде словаря, где ключом будет название предмета, а значением — его количество. В качестве такого словаря будем использовать специальную разновидность словарей из стандартной библиотеки — collections.Counter (см. предыдущий семинар).

>>> import collections
>>> dict_of_counters = {}
>>> for student, case in dict_of_lists.items():
...     dict_of_counters[student] = collections.Counter(case)

Теперь мы можем очень просто выяснить ответы на другие вопросы, например: «Какого предмета больше всего у Ксюши?» или «Сколько ластиков у Миши?».

>>> print('Самый многочисленный предмет в пенале Ксюши — это',
...       dict_of_counters['Ксюша'].most_common(1)[0][0])
Самый многочисленный предмет в пенале Ксюши  это ручка
>>> print('Количество ластиков у Миши:', dict_of_counters['Миша']['ластик'])
Количество ластиков у Миши: 0

Обратите внимание, что для несуществующих в Counter ключей значение равно нулю.

Предположим, что мы хотим добавить ещё какой-то предмет в чей-то пенал, указав имя ученика и название предмета.

>>> dict_of_counters['Ксюша']['ластик'] += 1
>>> dict_of_counters['Ксюша']['фломастер'] += 1

Обратите внимание, что для несуществующих в Counter ключей оператор += тоже работает.

Усложним задачу, пусть теперь, если используется имя ученика, которого ещё нет в словаре, то его нужно добавить. Ниже приводится несколько реализаций функции, которая делает такое обновление словаря, в порядке улучшения качества кода.

def add_item1(d, student, item):
    if student in d:
        d[student][item] += 1
    else:
        d[student][item] = collections.Counter([item])
        # или, аналогично:
        # d[student][item] = collections.Counter({item: 1})


def add_item2(d, student, item):
    if student not in d:
        d[student] = collections.Counter()
    d[student][item] += 1


def add_item3(d, student, item):
    case = d.setdefault(student, collections.Counter())
    case[item] += 1

В последнем примере используется метод словаря .setdefault(key, default). Этот метод возвращает значение словаря по ключу key, а если такого ключа ещё нет, то добавляет в словарь пару key: default и возвращает default.

Домашнее задание

Вам нужно написать программу, которая загадывает слова. Загадав существительное, программа показывает подсказку в виде распространённого словосочетания с этим существительным, в котором существительное заменено многоточием, и ждёт ответа пользователя, после чего сообщает, выиграл он или проиграл. Например, если загадано слово «снег», можно показать подсказку «белый …». Словосочетание можно подсмотреть в корпусе или довериться интуиции.

В задании обязательно использовать словарь. Программа должна уметь загадывать как минимум 5 разных слов (с разными подсказками, не менее трёх подсказок для каждого слова). Кроме того слова и подсказки должны храниться в отдельном CSV-файле, который загружается при запуске программы.

Дополнительные свойства программы по вариантам: 

  1. Пользователю даётся столько попыток угадать слово, сколько букв в слове;
  2. Многоточие должно содержать столько точек, сколько букв в слове;
  3. Пользователю даётся столько попыток угадать слово, сколько подсказок к этому слову;
  4. Многоточие должно содержать столько точек, сколько букв в подсказке;
  5. Программа показывает число попыток, которое пользователь уже сделал, чтобы угадать слово;
  6. Программа показывает число попыток, которое осталось пользователю до лимита в 3 попытки;
  7. Программа сообщает пользователю о том, что он выиграл или проиграл, разными случайными формулировками.

С CSV-файлами можно работать так же, как и с обычными файлами. Если данные в вашем файле разделены при помощи запятых, то:

  • открываете файл
  • читаете его по строкам
  • каждую строку делите по запятым при помощи .split(‘,’)
  • получаете массив с данными, содержащимися в конкретной строке.
  • делаете с ними что хотите

Выполните задание пройдя по ссылке в GitHub Classroom:


Улучшить эту страницу