【问题标题】:Is `iter(callable, sentinel)` still Pythonic?`iter(callable, sentinel)` 还是 Pythonic 吗?
【发布时间】:2020-05-12 06:50:36
【问题描述】:

iter函数的第二个参数对looping over objects that don't define themselves as iterable很有用,比如二进制文件:

response = b''
for block in iter(partial(f.read, 256), b''):
    response += block

然而,在 Python 3.8 中,我们现在有了“海象运算符”,What's new in Python 3.8 文章中提到了它作为解决上述确切问题的方法:

# Loop over fixed length blocks
while (block := f.read(256)) != '':
    process(block)

我想知道现在是否认为后者是“正确的方法”?如果是这样,是否需要iter 的第二个参数,因为表单上的任何代码

for x in iter(f, y):
    g(x)

现在也可以写成:

while (x := f()) != y:
    g(x)

我想可能仍然存在我们不想立即循环迭代的情况,例如b''.join(iter(partial(f.read, 256), b'')) 或一些代码(尽管它很快就会变得很麻烦)。 同样像for i, x in enumerate(iter(f, y)): 这样的循环可能很难转换为新语法(?)

The PEP for walrus 仅在示例 while h(x := f()): g(x) 中提到 2-arg iter,它说不能简单地将其转换为 iter

Python 通常对这类事情有非常精确的指导方针,但我无法找到任何针对这个特定问题的指导方针。你能帮帮我吗?

【问题讨论】:

  • f.read(256) 不是 iter 的 2 参数形式的有效第一个参数;我想你的意思是iter(lambda: f.read(256), b'')
  • 我相信,由于这是一个非常新的功能,因此需要一段时间才能看到在这种情况下哪个成为主要功能以及每个功能的优缺点。
  • iter(..., ...) 仍可用作构建迭代器的起点,例如,使用 itertools 模块定义的类型。
  • 从完全不同的角度来看,有人可能会争辩说iter(callable, sentinel)从来没有 Pythonic,因为它很少见。 :)
  • 那它怎么变成了“将代码转化为漂亮的、惯用的 Python”的推荐:P。我想它只是被推动但从未被采用......也许它应该被删除。

标签: python python-3.x loops iterator pep


【解决方案1】:

如果您主要对立即迭代迭代器感兴趣,则赋值表达式很有用,但它不能帮助您定义要在其他地方使用的迭代器。

例如,您可能希望创建一个迭代器,该迭代器将首先包装在 mapfilteritertools.islice 中,然后最终使用 for 循环迭代最终结果。

【讨论】:

  • 我想你可以使用(x for _ in count() if (x := f()) != y) 作为iter(f, y) 的海象版本。
  • 虽然我明白你的意思:使用 walrus 进行循环,并使用 iter 创建不立即循环的迭代器。
  • 即使在while 循环中,我认为:= 最适合用于简单的分配和检查。使用while True: x = f(x); if <some condition of x>: break; ... 编写的代码可能仍然最好
  • 即使这仍然略有不同:生成器永远运行,而不是在 x == y 时停止。
  • 好点。我想非迭代的情况很清楚。你是对的,在 while 循环的情况下,已经有两种方法可以做到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多