我打开了一个文件,我把它命名为“myfile”;我想从它创建两个不同的字典,但文件关闭我,我假设因为我在第一个循环中创建了第一个字典。 我得到一个空字典的直方图,我已经尝试使用myfile作为x并使用x而不是f作为第二个循环,我得到了这个“ValueError:关闭文件的I / O操作”。
另外,如果有所不同,我在一个类的函数中这样做。
有人知道如何使这项工作吗?
d = {}
d2 ={}
with myfile as f:
next(f)
for line in f:
k, v = line.split()
d[int(k)] = int(v)
next(f)
for line in f:
items = line.split()
key, values = int(items[0]), items[1:]
d2.setdefault(key, []).extend(values)
hist = defaultdict(list)
for key, values in d2.iteritems():
hist[len(values)].append(key)
histogram = dict(hist)
答案 0 :(得分:4)
你只是第一次通过循环来耗尽迭代器。因此,当你再次尝试循环时,没有什么可看的了。
将所有逻辑放在同一个循环中。我不太确定你的循环应该做什么,但它看起来像第一个循环,因为你应该只应用于每个奇数(0索引)行,这很容易用{{ 1}}。第二个循环似乎适用于每一行,所以我从那个循环开始,然后为它添加“第一个”循环的功能;像这样的东西:
enumerate
答案 1 :(得分:2)
要解决您提出的问题,请在第一次循环后调用f.seek(0)
然而,@ henry-keiter建议只对数据循环一次应该认真对待。
答案 2 :(得分:1)
我同意亨利的意见:除非你真的需要做一个双程算法,否则不要做seek()
。
你有没有理由不这样做?
此外,在第一个循环中使用next(f)
看起来很可疑:通常,如果你正在迭代某些东西,你不想对支持迭代的那个东西做任何其他事情。
我期待以下内容:
with myfile as f: ## FIXME: this is suspect. 'myfile' is accessible outside this
## `with` already, so there's something weird here.
for (index, line) in itertools.izip(itertools.count(), f):
if index % 2 == 1:
k, v = line.split()
d[int(k)] = int(v)
items = line.split()
key, values = int(items[0]), items[1:]
d2.setdefault(key, []).extend(values)
您可以在该文件上迭代单次传递。原始代码中的第一个循环似乎只关心文件中的奇数行,因此这次重写试图表达这个想法。
顺便说一下:with
在这里使用了。如果我们希望with
对资源的开启和关闭负责,并在with
的正文中为其命名,我们通常会这样做:
with open(...) as f:
...
但是编写的代码已经已经打开了它。这意味着此处的myfile
变量已在之前初始化,并且仍可在此with
之外访问。
如果我们使用try
/ finally
,我们会对代码更加公平,如下所示:
try:
... ## use myfile here instead of f
finally:
myfile.close()
代码更清楚地表明myfile
/ try
结束时finally
将被保证关闭。