0

所以我有一个文本文件,例如:

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
4

2 回答 2

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
于 2012-11-22T20:57:59.500 回答
1

您的代码中有几个不同的错误。导致您的异常的原因是您的函数data写入全局变量并且不返回任何内容,但是您以后的代码期望它返回可迭代的内容,例如序列或生成器。

您可以通过使顶级代码直接在全局字典上迭代来解决此问题,或者您可以摆脱全局并在其中创建字典data并在最后返回它。我建议后者,因为随着代码变得越来越复杂,全局变量很难处理。

这是它应该如何工作的粗略轮廓(我将中间部分粗略地留下,因为我稍后会讨论它):

def data(file):
    objects = {}

    # add stuff to objects dict

    return objects

你的下一个错误是剥离你的线条。您的代码当前使用自己的strip方法测试每一行的不等式。这是 Python 3 中的一个错误,因为lineline.strip具有无与伦比的类型。但即使有效,也毫无意义。我怀疑你试图消除空行,首先剥离它们,然后拒绝任何空行。您可以这样做:

if not line.strip():
    continue

这是 Python 社区中的一些人所说的“先看再跳”(LBYL)编程风格的一个例子,因为您正在检查可能是问题的东西。另一种选择是“请求宽恕比许可更容易”(EAFP)样式,您只需将可能出现问题的区域包装在一个try块中并捕获生成的异常。EAFP 风格有时被认为更“Pythonic”,所以稍后我会展示这种风格。

下一个错误是一个逻辑错误,而不是会导致错误的东西。您正在拆分您的行,并且您希望将它的两部分放入变量keyvalue. 但是,您对这些变量进行了两次单独的赋值,实际上它们最终得到了相同的值。这是一个你可以使用 Python 语法的一个很酷的特性,解包的地方。您可以将双值序列(例如列表或元组)一起分配给它们,而不是单独分配每个变量。Python 将负责将第一个值赋予第一个变量,将第二个值赋予第二个变量。这是它的样子:

key, value = line.split(":")

当然,如果行中没有冒号,这将失败,因此try如果我们使用 EAFP 风格的编码,这是我们放置块的好地方。这是一种方法:

try:
    key, value = line.split(":")
except ValueError:
    continue

您可以将try块放在循环中剩余的所有内容周围,然后让except块只包含pass(什么都不做,但忽略异常)。

最后,最后一个逻辑错误与构建嵌套字典的方式有关。您当前的方法是首先使用文件中的所有键和值构建一个字典,然后将它们分成单独的部分,每个天体一个。但是,如果每个对象的键相同,这将不起作用。例如,由于每个对象都有一个“Orbital Radius”键,因此它们都将相互覆盖,将该键放入单个字典中。

@sudo_o 的答案显示了如何构建内部字典并用值填充它(它几乎与我要写的相同)。我只是想发表我其余的解释!

于 2012-11-22T21:06:22.470 回答