Ввод данных в словарь
Итак, у меня есть текстовый файл, например:
RootObject: Sun
Object: Sun
Satellites: Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Ceres,Pluto,Haumea,Makemake,Eris
Radius: 20890260
Orbital Radius: 0
Object: Earth
Orbital Radius: 77098290
Period: 365.256363004
Radius: 6371000.0
Satellites: Moon
Object: Moon
Orbital Radius: 18128500
Radius: 1737000.10
Period: 27.321582
и я пытаюсь ввести его в словарь. Это то, что у меня есть, но я получаю сообщение об ошибке...
#d = dictionary
#new_d = new dictionary
file = open("data.txt","r")
d = {}
def data(file):
for line in file:
if line != line.strip:
continue
line = line.strip()
key = line.split(":")
val = line.split(":")
if key in d and key == "Object":
print(d)
d[key] = val
print(d)
new_d = {}
with file as x:
for d in data(x):
new_d[d["Object"]] = d
print(nd)
Я должен получить что-то вроде этого:
{' Earth': {'Satellites': ' Moon', 'Orbital Radius': ' 77098290', 'Object': ' Earth', 'Radius': ' 6371000.0', 'Period': ' 365.256363004'}, ' Moon': {'Orbital Radius': ' 18128500', 'Object': ' Moon', 'Radius': ' 1737000.10', 'Period': ' 27.321582'}, ' Sun': {'Satellites': ' Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Ceres,Pluto,Haumea,Makemake,Eris', 'Orbital Radius': ' 0', 'Object': ' Sun', 'Radius': ' 20890260', 'RootObject': ' Sun'}}
Я получаю эту ошибку:
Traceback (most recent call last):
File "planet2.py", line 21, in <module>
for d in data(x):
TypeError: 'NoneType' object is not iterable
2 ответа
Это будет хорошо делать:
file = open("data.txt","r")
def data(file):
dic = {}
for line in file:
# If line not blank
if line.strip() != '':
key,value = line.split(":")
if key == 'RootObject':
dic[key] = value.strip()
elif key == 'Object':
# Get the Object value i.e Earth, Moon, Sun
obj = value.strip()
# Create entry with obj key and blank dictionary value
dic[obj]={}
else:
# Populate the blank dictionary with key, value pairs
dic[obj][key] = value.strip()
return dic
planets = data(file)
# Usage
print planets
print planets['Earth']
print planets['Earth']['Radius']
Выход:
# The whole dictionary
{'Sun': {'Satellites': 'Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Ceres,Pluto,Haumea,Makemake,Eris', 'Orbital Radius': '0', 'Radius': '20890260'}, 'Moon': {'Orbital Radius': '18128500', 'Radius': '1737000.10', 'Period': '27.321582'}, 'Earth': {'Satellites': 'Moon', 'Orbital Radius': '77098290', 'Radius': '6371000.0', 'Period': '365.256363004'}}
# The Earth dictionary
{'Satellites': 'Moon', 'Orbital Radius': '77098290', 'Radius': '6371000.0', 'Period': '365.256363004'}
# The Earth's radius
6371000.0
В вашем коде есть несколько разных ошибок. То, что вызывает ваше исключение, заключается в том, что ваша функция data
записывает в глобальную переменную и ничего не возвращает, но ваш более поздний код ожидает, что он вернет что-то итерируемое, например последовательность или генератор.
Вы можете исправить это, либо сделав код верхнего уровня итерацией непосредственно в глобальном словаре, либо вы можете избавиться от глобального и создать словарь в data
и верните его в конце. Я предлагаю последнее, поскольку с глобальными переменными трудно иметь дело, так как ваш код становится все сложнее.
Вот примерный план того, как это должно работать (я оставляю среднюю часть отрывочной, так как я буду обсуждать это позже):
def data(file):
objects = {}
# add stuff to objects dict
return objects
Ваша следующая ошибка заключается в удалении ваших строк. Ваш код в настоящее время проверяет каждую строку на наличие неравенства strip
метод. Это ошибка в Python 3, так как line
а также line.strip
имеют несравненные типы. Но даже если бы это сработало, это было бы бессмысленно. Я подозреваю, что вы пытались убрать пустые строки, сначала удалив их, а потом отвергнув все пустые. Вот как вы можете это сделать:
if not line.strip():
continue
Это пример того, что некоторые люди в сообществе Python называют стилем программирования "смотри, прежде чем прыгнуть" (LBYL), так как вы проверяете что-то, что может быть проблемой, прежде чем это станет. Альтернативой является стиль "проще просить прощения, чем разрешения" (EAFP), когда вы просто оборачиваете область, где проблема может возникнуть в try
заблокировать и перехватить сгенерированные исключения. Стиль EAFP иногда считается более "питоническим", поэтому я покажу этот стиль чуть позже.
Следующая ошибка - логическая, а не та, которая вызовет ошибку. Вы разбиваете свою строку и хотите получить две ее части в переменных key
а также value
, Однако вы делаете два отдельных присваивания этим переменным, и на самом деле они заканчиваются одинаковым значением в каждой. Это место, где вы можете использовать классную функцию синтаксиса Python - распаковку. Вместо того, чтобы назначать каждую переменную отдельно, вы можете назначить двухзначную последовательность (например, список или кортеж) для них обоих вместе. Python позаботится о присвоении первого значения первой переменной и второго значения второй переменной. Вот как это выглядит:
key, value = line.split(":")
Конечно, это не удастся, если в строке нет двоеточия, поэтому это хорошее место для нас try
блок, если мы используем EAFP-стиль кодирования. Вот один из способов сделать это:
try:
key, value = line.split(":")
except ValueError:
continue
Вы могли бы вместо этого поставить try
блок вокруг всего, что остается в цикле, а затем пусть except
блок содержит только pass
(который ничего не делает, но игнорирует исключение).
Наконец, последняя логическая ошибка, которую вы имеете, связана с тем, как вы строите свои вложенные словари. Ваш текущий подход заключается в том, чтобы сначала создать один словарь со всеми ключами и значениями из вашего файла, а затем разделить их на отдельные части, по одному на небесный объект. Однако это не работает, если ключи для каждого объекта одинаковы. Так как, например, у каждого объекта есть ключ "Орбитальный радиус", все они будут писать друг над другом, помещая этот ключ в один словарь.
Ответ @sudo_o показывает, как построить внутренний словарь и заполнить его значениями (это почти идентично тому, что я собирался написать). Я просто хотел опубликовать остальные мои объяснения!