从fi创建两个词典时保持文件打开

2024-04-26 12:36:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我打开了一个文件,我把它命名为“myfile”;我想用它创建两个不同的字典,但是文件关闭了,我假设是因为我在第一个循环中创建了第一个字典。 我得到了一个直方图的空字典,我试着用myfile作为x,用x代替f作为第二个循环,我得到了这个“ValueError:I/O operation on closed file”。你知道吗

另外,我是在一个类的函数中这样做的,如果这有区别的话。你知道吗

有人知道怎么做吗?你知道吗

    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)

Tags: 文件keyinfor字典lineitemsmyfile
3条回答

第一次循环遍历迭代器就是在耗尽迭代器。因此,当您再次尝试循环时,就没有什么可看的了。你知道吗

把你所有的逻辑放在同一个循环里。我不太清楚你的循环应该做什么,但它看起来像你的第一个循环,它应该只适用于每一个奇数(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)

我同意亨利的观点:不要做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结束时关闭。你知道吗

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

然而,@henrykeiter关于只循环一次数据的建议应该被认真对待。你知道吗

相关问题 更多 >