0

我的想法是摆脱用户不断使用seek(0)来重置文本文件读取的方式。

所以相反,我尝试创建一个MyReadercollections.Iterator然后使用.reset()替换seek(0),然后它通过保留一个self.iterable对象从上次产生的位置继续。

class MyReader(collections.Iterator):
    def __init__(self, filename):
        self.filename = filename
        self.iterable = self.__iterate__()

    def __iterate__(self):
        with open(self.filename) as fin:
            for line in fin:
                yield line.strip()

    def __iter__(self):
        for line in self.iterable:
            yield line

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

    def reset(self): 
        self.iterable = self.__iterate__()

用法类似于:

$ cat english.txt
abc
def
ghi
jkl

$ python

>>> data = MyReader('english.txt')
>>> print(next(data))
abc
>>> print(next(data))
def
>>> data.reset()
>>> print(next(data))
abc

我的问题是这是否已经存在于 Python-verse 的某个地方?特别是。如果已经有一个本地对象可以做这样的事情,我想避免重新发明轮子=)

如果不存在?这个对象看起来有点不合常理吗?因为它说它是一个迭代器,但真正的迭代器实际上是self.iterable并且其他函数围绕它进行“重置”。

4

2 回答 2

3

我认为这取决于您的实际情况。假设您只想摆脱file.seek(0),它可以很简单:

class MyReader:
    def __init__(self, filename, mode="r"):
        self.file = open(filename, mode)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.close()

    def __iter__(self):
        self.file.seek(0)
        for line in self.file:
            yield line.strip()

    def close(self):
        self.file.close()

你甚至可以像普通的上下文管理器一样使用它:

with MyReader("a.txt") as a:
    for line in a:
        print(line)
    for line in a:
        print(line)

输出:

sdfas
asdf
asd
fas
df
asd
f
sdfas
asdf
asd
fas
df
asd
f
于 2018-02-12T10:31:55.073 回答
1

我对你的MyReader课有几点批评。我打算发布一个替代方案,它是一个上下文管理器,但 Sraw 打败了我。;)

您不应使用以双下划线开头和结尾的名称,例如__iterate__. 这样的名称本质上是为语言实现者保留的,如果将官方__iterate__魔法方法添加到语言中,您的代码将会中断。如果你想要一个私有方法,你可以命名它_iterate

该方法有一个小问题:仅当文件已完全读取 current 时才退出__iterate__它的块,因此如果实例被重置,那么您将有一个旧的打开文件,正在使用文件描述符。当然,当程序退出(或删除实例)时,它最终会关闭,但恕我直言,这很混乱。withself.iterableMyReaderMyReader

另外,我对yield line.strip(). 当然,在大多数情况下阅读文本文件时它很方便,但在某些情况下,调用者可能想要查看任何前导或尾随空格,而您已经从他们那里拿走了这个选项。

顺便说一句,该__iter__方法是多余的:如果您消除该方法,您的类仍然会执行它应该做的事情。

于 2018-02-12T11:14:58.760 回答