Вложенные структуры
Допустим, вы где-то скачали файл с данными о кино. Но выглядит он совсем жутко:
films_data = [ "adult": false, "original_title": "Ariel", "overview": "С героем фильма шахтером Таисто случается серия неудач…", "budget": 0, "release_date": "1988-10-21", "genres": [ "id": 18, "name": "драма" >, "id": 80, "name": "криминал" >, "id": 35, "name": "комедия" > ], >, "adult": false, "original_title": "Varjoja paratiisissa", "overview": "", "budget": 0, "release_date": "1986-10-17", "genres": [ "id": 18, "name": "драма" >, "id": 35, "name": "комедия" > ], >, ...
Достаём первый фильм
Данная структура — это список. Снаружи стоят квадратные скобки, а внутри через запятую лежат огромные словари с информацией о фильмах. Попробуем достать первый фильм:
first_film = films_data[0] print(first_film)
Как ни странно, из всей кучи фильмов перед вами осталась только информация о первом:
"adult": false, "original_title": "Ariel", "overview": "С героем фильма шахтером Таисто случается серия неудач…", "budget": 0, "release_date": "1988-10-21", "genres": [ "id": 18, "name": "драма" >, "id": 80, "name": "криминал" >, "id": 35, "name": "комедия" > ] >
Достаём название фильма
Информация о фильме — это обычный словарь.
first_film = films_data[0] first_film_title = first_film['original_title'] print(first_film_title) # Вывелось Ariel
Достаём жанры фильма
Жанры фильма в нашей структуре — это список внутри словаря внутри списка. Достанем их:
first_film = films_data[0] first_film_genres = first_film['genres'] print(first_film_genres)
[ "id": 18, "name": "драма" >, "id": 80, "name": "криминал" >, "id": 35, "name": "комедия" > ]
По жанрам тоже легко «путешествовать»:
first_film = films_data[0] first_film_genres = first_film['genres'] for genre in first_film_genres: print(genre)
Этот код выведет все жанры через пустую строку:
"id": 18, "name": "драма" > "id": 80, "name": "криминал" > "id": 35, "name": "комедия" >
Меньше переменных
Сейчас, чтобы добраться до id первого жанра придётся создать аж 4 переменные:
first_film = films_data[0] first_film_genres = first_film['genres'] first_genre = first_film_genres[0] first_genre_id = first_genre['id']
Переменные можно не создавать, если расставить индексы в цепочку:
first_genre_id = films_data[0]['genres'][0]['id']
Когда Python прочтёт films_data[0] , он сразу достанет первый элемент в списке films_data и подставит его вместо films_data[0] . Когда он начнёт читать дальше, он увидит [‘genres’] , и возьмёт этот ключ от того, что только что посчитал слева, т.е. от первого фильма. И так далее, Python по цепочке распутает эту конструкцию сам, без дополнительных переменных.
Как создать вложенную структуру
Допустим, у вас откуда-то есть данные о фильмах:
first_film_title = "Пила 1" first_film_budget = 100 second_film_title = "Пила 2" second_film_budget = 200
Очень легко собрать из этого список:
budgets = [first_film_budget, second_film_budget] # Или так budgets = [] budgets.append(first_film_budget) budgets.append(second_film_budget)
Так же легко собрать для каждого фильма словарь:
first_film = "title":"Пила 1", "budget": 100 > # Или так first_film = dict() first_film['title'] = "Пила 1" first_film['budget'] = 100
и положить эти словари в список:
films = [first_film, second_film] # Или так films = [] films.append(first_film) films.append(second_film)
Получится сложная конструкция:
[ 'budget':100, 'title':'Пила 1' >, 'budget':200, 'title':'Пила 2' > ]
Попробуйте бесплатные уроки по Python
Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.
Переходите на страницу учебных модулей «Девмана» и выбирайте тему.
Как получить значение из вложенного словаря
Добрый день, подскажите, пожалуйста, как получить значение по ключу из вложенного словаря? Например, как обратиться к E-2 -> V_app, что бы получить «300»?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
V_app = 200 a_app = 0 T_app = 36 data = {"E-1":{"name":"E-1", "V_app":V_app, "a_app":a_app, "T_app":T_app}} vibor = 1 if vibor == 1: data["E-2"] = {"E-2":{"name":"E-2", "V_app":300, "a_app":0.2, "T_app":250}} print(data) print("\n") print(data["E-2"]) print("\n") #print(data["E-2"]["V_app"])
Лучшие ответы ( 1 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Как получить значение найденного элемента словаря?
Как можно получить значение найденного элемента словаря? Например If dicTemp2.Exists(key) Then.
Получить значение вложенного инпута
Я формирую массив из таблицы для передачи в пост var tableArray = ; $("table#tblsel.
Как в индексаторе моей реализации «словаря» получить элемент словаря без перебора?
Пытался сдать лабу преподавателю, суть которой в открытом хешировании, создал свой словарь (класс.

Получение данных из вложенного словаря
Здравствуйте, я новичок в python, недавно начал изучать и сразу появилась проблема со сложным.
Изменение значения вложенного словаря
Добрый день! При изменении значения во вложенном словаре plita=’5′, значение изменяется и в.
954 / 340 / 114
Регистрация: 04.08.2018
Сообщений: 2,533

Сообщение было отмечено Михалыч как решение
Решение
dict.get(key[, default]) — возвращает значение ключа, но если его нет, не бросает исключение, а возвращает default (по умолчанию None).
Добавлено через 4 минуты
print(data['E-2'].get('E-2').get('V_app'))
Добавлено через 1 минуту
Вывод:
Доступ к вложенному словарю по списку ключей
Вопрос: как из ‘value2A’ сделать любое другое значение? По возможности используйте dict[key] = ‘value’ , чтобы я мог настроить добавление элемента dict[addedkey] = ‘addedvalue’ и его удаление del dict[delkey] или подскажите другие варианты это сделать (это мне тоже надо, забыл сразу указать, а создавать новый вопрос как по мне не очень логично).
dictonary['level1B']['level2B'] = 'newvalue' #это работает, но нужно знать уровень вложенности dictonary[keylist] = 'newvalue' #нужен рабочий аналог этого действия, т. к. "TypeError: unhashable type: list"
Вложенность dictonary и длина keylist могут быть любыми.
Я пробовал получить каждую вложенность в список, изменить самую глубокую и «собрать» словарь обратно, но либо я накосячил в коде, либо метод не работает. Вот метод для получения вложенности (он рабочий):
def getlevel(dictonary, keylist): res = dictonary for d in keylist: res = res[d] return dictonary
P.S. Имена переменных любые, главное, чтобы я понял, где словарь, а где список ключей.
EDIT: На самом деле, задача состоит в возможности не только изменения, но и добавления и удаления ключей и значений.
EDIT2:В списке ключей каждый следующий ключ для следующего «уровня» словаря. Первый элемент — ключ для первого «уровня», второй для второго и т.д. И каждый новый «уровень» — значение ключа на предыдущем «уровне». И значение последнего ключа в списке ключей не обязано быть определенным типом данных; это тоже может быть словарь, но там я разберусь. «Уровень» — словарь-значение у текущего ключа в списке ключей. Первый «уровень» — «корневой словарь», у меня в нём определены level1A и level1B
Вложенные словари
В качестве значения ключа словаря может выступать любой объект: число, строка, список или словарь. Вложенные коллекции часто используются для структурирования данных. Рассмотрим пример: словарь из списков, описывающий содержание пеналов учеников класса 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() 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 .
collections.defaultdict
Интуиция
defaultdict — это такой словарь, который старается сам правильно обработать отсутствие ключа в словаре.
Обычно мы сообщаем ему, какого типа должно по умолчанию быть значение, соответствующее ключу.
Зная поумолчальный тип значений, defaultdict , будет заводить тривиальное значение этого типа каждый раз, когда мы будем обращаться к ключу, которого на момент обращения нет в словаре.
В таком случае мы не получим ошибку KeyError (такого ключа в словаре нет) , а сразу увидим значение, о котором подсуетился defaultdict .
тривиальное значение какого-то типа тут – что-то максимально простое для этого типа. Для целых чисел – 0, для нецелых – 0.0, для строк – пустая строка, для списков – пустой список.
Пример использования
defaultdict обычно нужен там, где для обычного словаря вам пришлось бы писать
my_dict = <> . if cat not in my_dict.keys(): my_dict[cat] = '' # или 0.0 или 0 или [] else: my_dict[cat] += mlem # или .append(mlem)
вместо этого можно написать
from collections import defaultdict as dd # погуглите import as если забыли в чём суть as my_dict = dd(str) . my_dict[cat] += mlem # обработка отсутствия кота в ключах произошла автоматически
lists comprehension (демо-версия)
это удобный способ сокращать создание или заполнение списков. Он иногда будет появляться в примерах для экономии места, поэтому честно о нём рассказать.
О дебаггинге lists comprehension
В одной строке оказываются несколько разных действий. Поэтому информация о том, что ошибка произошла в строке с list comprehension, более неоднозначна, чем то же про обычную строку.
Если что-то не работает в строке с list comprehension, сразу переписывайте её без list comprehension и чините логику в “развёрнутом” виде, а потом сворачивайте обратно когда убедитесь, что с логикой всё ок.
Основная идея
li = [] for elem in [1,2,3]: li.append(elem)
можно записать так:
li = [elem for elem in [1,2,3]]
вложенность обрабатывается слева направо:
def cond(smth): res = isinstance(smth, int) and smth % 2 == 0 return res li = [] for i in [0,1,2]: for j in [3,4]: if cond(i*j): li.append(i*j) li2 = [i*j for i in [0,1,2] for j in [3,4] if cond(i*j)] # имхо более читаемо как в li3 li3 = [i*j for i in [0,1,2] for j in [3,4] if cond(i*j)]
csv.DictReader
Отличный способ читать csv. Авторский конспект на подходе, временно ссылка на подходящий.
Домашнее задание
больше, чем обычно, и на подольше
Вам нужно написать программу, которая загадывает персонажей “Звёздных войн”. Загадав персонажа, программа показывает подсказку в виде частотного биграммного словосочетания из реплик этого персонажа, и ждёт ответа пользователя, после чего сообщает, угадал он или нет. Например, если загадан персонаж «THREEPIO», можно показать подсказку «Master Luke». Реплики персонажей нужно брать из сценариев ЗВ, ссылка на страницу датасета сценариев.
Пользователь может попросить подсказку. Тогда нужно выдать в ответ какую-то (если есть) информацию о загаданном персонаже из датасета2 ссылка на страницу датасета базы знаний ЗВ.
В задании обязательно использовать словарь. Когда читаете csv, используйте DictReader.
Дополнительные свойства программы по вариантам:
- После каждой попытки угадать персонажа вероятность того, что пользователю разрешена ещё одна попытка, обратно пропорциональна частоте реплик персонажа – можно поиграть с конкретной математикой, но отгадывая редких персонажей должно быть проще получить доп. попытки ссылка на SO;
- Пользователь может выбрать подмножество персонажей, одного из которых загадает программа – нужно спросить список интересных персонажей в начале работы программы;
- Пользователю за раз показывается столько реплик персонажа, сколько в его имени букв по модулю 4;
- Вместе с репликой подсказывается, из какого сезона взята реплика;
- Вместе с репликой подсказывается, чьи реплики были в сценарии до и после показанной;
- Программа показывает не биграммы, а триграммы;
- В время (см. либу datetime) с полуночи до часу ночи программа сообщает пользователю о том, что он выиграл или проиграл, напечатав имя персонажа ASCII-артом (генерировать его не надо, можно захардкодить).