代码之家  ›  专栏  ›  技术社区  ›  janluke

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

  •  0
  • janluke  · 技术社区  · 7 年前

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

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

    编辑:

    几个月后我刚读到这个问题,我问了这个问题,觉得有点愚蠢:)。

    正如下面的答案所写,a __iter__ 有副作用的方法是一件坏事。如果要多次迭代对象,那么每次调用时只需返回一个新的迭代器对象 __iter公司__

    class IterableFile:
        def __iter__(self):
           return FileIterator(self)
    

    回想起来,这是很明显的,我想这就是为什么我现在觉得自己很愚蠢的原因。不知道我在想什么,但我认为我不愿意有两个独立的类的原因是,每个新的迭代器都需要创建一个新的文件处理程序(我的SpecialFile类只是一个文本/二进制文件之上的接口),这在当时让我觉得“过分”和奇怪。

    2 回复  |  直到 6 年前
        1
  •  2
  •   user2357112    7 年前

    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()
    
        2
  •  0
  •   Prune    7 年前

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

    然而,请记住关于“小心灵的妖精”的严格规定:

    • 你的 reset 改进程序流程?

    如果你已经为那些需要理解和维护这些的人——包括你未来的自己——讲述了这些,那么 复位 很可能是个好习惯。我很怀疑,但我在工作中见过这种情况。

    旁注 :为什么需要 复位 当你第一次构造迭代器的时候?