0

我打开了一个文件并将其命名为“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)
4

3 回答 3

4

您只是通过第一次循环遍历它来耗尽迭代器。因此,当您再次尝试循环时,就没有什么可看的了。

只需将所有逻辑放在同一个循环中即可。我不太确定你的循环应该做什么,但它看起来像你拥有的第一个循环,它应该只适用于每个奇数(0 索引)行,这很容易用enumerate. 第二个循环似乎适用于每一行,所以我将从那个循环开始,然后将“第一个”循环的功能添加到它;像这样的东西:

with myfile as f: # Better:  with open('/some/file.txt', 'rb') as f:
    for i, line in enumerate(f):
        # "Second" loop
        items = line.split()
        key, values = int(items[0]), items[1:]
        d2.setdefault(key, []).extend(values)

        # "First" loop
        if i % 2 != 0: # Only process odd-numbered lines
            k, v = items
            d[int(k)] = int(v)
于 2013-10-28T21:14:59.873 回答
2

要解决您提出的问题,然后f.seek(0)在第一个循环后调用

但是,@henry-keiter 建议只循环一次数据,应该认真对待。

于 2013-10-28T21:16:56.253 回答
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此处的变量已较早初始化,并且仍然可以在 this 之外访问with

如果我们使用try/ finally,我们会更公正地处理代码,如下所示:

try:
    ...  ## use myfile here instead of f
finally:
    myfile.close()

代码更清晰的地方将保证在/myfile的末尾关闭。tryfinally

于 2013-10-28T21:40:09.263 回答