自定义生成器用于文件筛选

时间:2016-05-15 07:38:18

标签: python

我正在围绕open编写一个小包装器类,它将从文本文件中过滤出特定行,然后在将它们传递回用户之前将它们拆分为名称/值对。当然,这个过程有助于使用生成器实现。

我的“文件”类

class special_file:
    def __init__(self, fname):
        self.fname = fname

    def __iter__(self):
        return self

    def __next__(self):
        return self.next()

    def next(self):
        with open(self.fname, 'r') as file:
            for line in file:
                line = line.strip()
                if line == '':
                    continue
                name,value = line.split()[0:2]
                if '%' in name:
                    continue
                yield name,value
            raise StopIteration()

用户名代码

for g in special_file('input.txt'):
    for n,v in g:
        print(n,v)

遗憾的是,我的代码有两个巨大的问题:1)special_file返回一个生成器,当它确实需要返回一个元组时,2)StopIteration()异常永远不会被提升所以文件无限重复读取。我怀疑这两个问题是相关的,但我对生成器和可迭代序列的理解相当有限。我是否遗漏了一些关于实施发电机的痛苦明显的事情?

编辑:

我通过将第一个生成器移动到循环外部然后循环遍历它来修复我的无限读取问题。

g = special_file('input.txt')
k = next(g)
for n,v in k:
    print(n,v)

但是,我希望用户能像普通电话open一样使用它:

for n,v in special_file('input.txt'):
    print(n,v)

2 个答案:

答案 0 :(得分:2)

在使用生成器方面,您已经实现了迭代器。直接写出发电机。

def special_file(filename):
    with open(filename, 'r') as file:
        for line in file:
            line = line.strip()
            if line == '':
                continue
            name, value, *_ = line.split()
            if '%' in name:
                continue
            yield name, value

请参阅here,了解可迭代的含义,迭代器的含义以及使用它们的python协议。

答案 1 :(得分:1)

只需更改

def __iter__(self):
    return self

def __iter__(self):
    return next(self)

它按预期工作!

感谢@ Leva7的建议。