在Python中,当调用__iter__时“重置”迭代器是一种不好的做法吗?

时间:2018-10-04 16:54:08

标签: python iterator iterable

例如,假设我有一个用于迭代文件内记录的类:

class MySpecialFile:
    ...
    def reset(self):
        self._handle.seek(0)

    def __iter__(self):
        self.reset()
        return self

2 个答案:

答案 0 :(得分:1)

iter应该没有副作用。通过违反这一假设,您的代码会破坏各种情况。例如,关于事物是否可迭代的标准测试:

try:
    iter(thing)
except TypeError:
    do_whatever()

将重置您的文件。同样,itertools consume recipe

def consume(iterator, n=None):
    "Advance the iterator n-steps ahead. If n is None, consume entirely."
    # Use functions that consume iterators at C speed.
    if n is None:
        # feed the entire iterator into a zero-length deque
        collections.deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)

将产生错误的文件位置,而不是在n之后前进consume(your_file, n)条记录。在循环之前用next跳过前几条记录也会失败:

f = MySpecialFile(whatever)
next(f) # Skip a header, or try, anyway.
for record in f:
    # We get the header anyway.
    uhoh()

答案 1 :(得分:0)

任何颠覆语言构造的预期流程的行为都是危险的信号,比“代码气味”更糟。这不是特定于Python的。它适用于任何语言或系统。

但是,请记住关于“小头脑的妖精”的观点:

  • 您的reset是否改善了程序流程?
  • 生成的代码是否易于阅读和理解?

如果您已经为需要理解和维护这一点的人们(包括您将来的自我)介绍了这些内容,那么reset可能是一个好习惯。我对此表示怀疑,但是我已经在工作中看到过这种情况。

附带说明:为什么在初次构造迭代器时需要reset