如何限制循环的迭代次数?

2024-04-18

假设我有一个项目列表,我想迭代其中的前几个:

items = list(range(10)) # I mean this to represent any kind of iterable.
limit = 5

简单的实现

来自其他语言的 Python 新手可能会编写这样完美可用且高性能(如果不符合语法)的代码:

index = 0
for item in items: # Python's `for` loop is a for-each.
    print(item)    # or whatever function of that item.
    index += 1
    if index == limit:
        break

更惯用的实现

但Python有枚举,它很好地包含了大约一半的代码:

for index, item in enumerate(items):
    print(item)
    if index == limit: # There's gotta be a better way.
        break

所以我们将额外的代码减少了一半。但一定有更好的方法。

我们可以近似下面的伪代码行为吗?

如果枚举采用另一个可选的stop参数(例如,它需要一个start像这样的论点:enumerate(items, start=1))我认为这是理想的,但下面的内容不存在(请参阅关于枚举的文档在这里 https://docs.python.org/3/library/functions.html#enumerate):

# hypothetical code, not implemented:
for _, item in enumerate(items, start=0, stop=limit): # `stop` not implemented
    print(item)

请注意,无需命名index因为没有必要引用它。

有没有一种惯用的方式来写上面的内容?如何?

第二个问题:为什么这没有内置到枚举中?


如何限制 Python 中循环的迭代次数?

for index, item in enumerate(items):
    print(item)
    if index == limit:
        break

有没有更短、更惯用的方式来写上面的内容?如何?

包括索引

zip停止在其参数的最短迭代上。 (与行为相反zip_longest,它使用最长的可迭代对象。)

range可以提供一个有限的可迭代对象,我们可以将其与主可迭代对象一起传递给 zip。

所以我们可以通过一个range对象(及其stop论证)到zip并像有限枚举一样使用它。

zip(range(limit), items)

使用Python 3,zip and range返回可迭代对象,它通过管道传输数据,而不是在中间步骤的列表中具体化数据。

for index, item in zip(range(limit), items):
    print(index, item)

要在 Python 2 中获得相同的行为,只需替换xrange for range and itertools.izip for zip.

from itertools import izip
for index, item in izip(xrange(limit), items):
    print(item)

如果不需要索引,itertools.islice

您可以使用itertools.islice:

for item in itertools.islice(items, 0, stop):
    print(item)

这不需要分配给索引。

构成enumerate(islice(items, stop))获取索引

正如 Pablo Ruiz Ruiz 指出的,我们还可以用 enumerate 来组合 islice。

for index, item in enumerate(islice(items, limit)):
    print(index, item)

为什么这个没有内置到enumerate?

下面是用纯 Python 实现的枚举(可以进行修改以获得注释中所需的行为):

def enumerate(collection, start=0):  # could add stop=None
    i = start
    it = iter(collection)
    while 1:                         # could modify to `while i != stop:`
        yield (i, next(it))
        i += 1

对于那些已经使用枚举的人来说,上面的性能会较差,因为它必须检查是否是时候停止每次迭代。如果没有得到停止参数,我们可以检查并使用旧的枚举:

_enumerate = enumerate

def enumerate(collection, start=0, stop=None):
    if stop is not None:
        return zip(range(start, stop), collection)
    return _enumerate(collection, start)

这项额外的检查会对性能产生轻微的影响,可以忽略不计。

As to whyenumerate 没有 stop 参数,这最初是提议的(参见PEP 279 https://www.python.org/dev/peps/pep-0279/):

该功能最初提出时带有可选启动 并停止争论。 GvR [Guido van Rossum] 指出函数调用enumerate(seqn, 4, 6)有一个替代的、合理的解释为 一个将返回第四个和第五个元素的切片 顺序。为了避免歧义,可选参数是 尽管这意味着失去循环计数器的灵活性,但还是下降了。 这种灵活性对于以下常见情况最为重要 从一开始计数,如:

for linenum, line in enumerate(source,1):  print linenum, line

所以显然start之所以被保留,是因为它非常有价值,并且stop被删除是因为它的用例较少并且导致新函数的使用混乱。

避免使用下标表示法进行切片

另一个答案说:

为什么不简单地使用

for item in items[:limit]: # or limit+1, depends

这里有一些缺点:

  • 它仅适用于接受切片的迭代,因此它更受限制。
  • 如果它们接受切片,它通常会在内存中创建一个新的数据结构,而不是迭代引用数据结构,从而浪费内存(所有内置对象在切片时都会进行复制,但是,例如,numpy 数组在切片时会生成一个视图)。
  • 不可切片的可迭代对象需要其他类型的处理。如果您切换到惰性评估模型,则还必须使用切片更改代码。

当您了解限制以及它是否生成副本或视图时,您应该仅使用带下标表示法的切片。

结论

我认为现在 Python 社区知道了 enumerate 的用法,争论的价值将超过混乱成本。

在那之前,您可以使用:

for index, element in zip(range(limit), items):
    ...

or

for index, item in enumerate(islice(items, limit)):
    ...

或者,如果您根本不需要索引:

for element in islice(items, 0, limit):
    ...

并避免使用下标表示法进行切片,除非您了解限制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何限制循环的迭代次数? 的相关文章

随机推荐

  • 如何为 HDFS 递归列出子目录?

    我在 HDFS 中递归创建了一组目录 如何列出所有目录 对于普通的 UNIX 文件系统 我可以使用以下命令来做到这一点 find path type d print 但我想为 HDFS 得到类似的东西 递归列出目录内容hadoop dfs
  • 仅绘制 y 轴,不绘制其他内容

    我想创建一个仅显示 y 轴 包括网格 数字和标签 的图 但我不想显示绘图或 x 轴 这可以吗 创建绘图时 您只需指定一些选项 特别要注意的是axes type and xlab plot runif 10 runif 10 xlim c 0
  • 如何在java中使用gson解码json字符串?

    我有一个json字符串 社交网络Qaiku的流 我怎样才能用Java解码它 我已经搜索过 但任何结果都对我有用 谢谢 对象反序列化的标准方法如下 Gson gson new Gson MyType obj gson fromJson jso
  • 为什么删除相关行 boot() 中的行不会被触发?

    在我的 Laravel 5 7 应用程序中 我有 2 个表 Tag TagDetail 一对一关系 第二个表将图像上传到存储和图像字段 我想使用引导方法自动删除相关行和图像 结果删除与 TagDetail 相关的 Tag 行被删除 但 Ta
  • 如何返回派生类型?

    我有一个 Validator 类及其派生类 当我尝试返回指向派生类的指针时 方法返回基类 验证器 而不是派生类 class Validator public std string m name BaseValidator static co
  • 对象类和数组 - 为什么它返回“null”? [java]

    我编写了一个小类 它创建一个包含 3 个数组的报表对象 在创建对象时 这些数组用值进行初始化 然而 当我测试该类以查看例如部门数组中的内容时 它会打印出数组元素为空 为什么 class Report declare instance var
  • 更新整数列中的特定位

    我有一个 mysql 表 其中用户权限存储为位掩码 user permissions Admin 31 User 13 16 8 4 2 1 Admin gt 1 1 1 1 1 gt 16 8 4 2 1 gt 31 User gt 0
  • android中的react-native-snap-carousel上手动水平滚动的问题

    我正在使用react native snap carousel来显示横幅 它在 iOS 中的手动滚动和间隔后自动滚动都运行良好 但在 Android 中手动滚动时面临两个问题 对于某些设备 特别是三星 它会卡在第三个索引处 手动完成时 但自
  • 在 Mac 上开发 .Net 应用程序? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我是 Net 开发人员 开始使用 Mac OS 我在这个系统上唯一怀念的是 VISUAL STUDIO 我不想使用两个系统 你认为如何开发 Ne
  • Impala 表中的压缩

    我想了解 Impala 表中的压缩 但找不到可供研究的材料 有哪些不同的技术以及我在哪里可以找到研究它的材料 主要技术为compaction是为了避免small file problem这取决于您的用例 例如 您可能有一个将小文件写入的进程
  • 函数式 GUI 编程可能吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我最近发现了 FP bug 试图学习 Haskell 到目前为止所看到的东西给我留下了深刻的印象 一流的函数 惰性求值和所有其他好处 我还不是专
  • Jfrog CLI 不尊重配置的 API 密钥

    我正在使用 Powershell DSC 设置 Windows Server 2012 R2 盒子 作为配置过程的一部分 我将配置 jfrog exe 并作为服务帐户执行配置命令 jfrog rt config url localArtif
  • 读取 WCF 消息正文两次 - “消息无法读取”

    我有一个 WCF 消息 Channels Message 我正在尝试使用 GetBody 提取正文 但是 我注意到我只能执行一次 如果我尝试再次使用 GetBody 我会收到 此消息无法支持该操作 因为它已被读取 知道如何重新阅读邮件正文吗
  • F# 有异步验证库吗?

    我在代码中经常使用 asyncResult 但它会在第一个错误时退出 asyncResult let a allGood let b thisReturnsError let c neverExecuted 但有时我想执行所有函数并总结错误
  • 具有多个条件的 SqlAlchemy 案例

    我正在尝试做这样的事情 x db session query Candidate func count case Jobs interview type PHONE SCREEN and Jobs interview type INCLIN
  • 补丁优先级及其对 Criminsi 基于范例的修复的影响

    我正在尝试实现基于示例的修复 如提议的Criminsi http research microsoft com pubs 67276 criminisi tip2004 pdf等等人 以其原始格式 在进行进一步优化之前 我有一些理论上的疑问
  • 从BackgroundWorker C# 更改控件的属性

    我正在尝试从目录加载一堆文件 在加载时显示进度条状态以及显示正在处理哪个文件的标签 private void FileWorker DoWork object sender DoWorkEventArgs e for int i 0 i l
  • 从 URL 加载图像

    我正在尝试根据以下教程在我的应用程序中加载一些图像 http www anddev org novice tutorials f8 imageview with loading spinner t49439 html http www an
  • NSIS 滚动许可证欢迎屏幕

    我的安装程序在与滚动许可证插件交互时遇到问题 安装程序在没有插件的情况下也能很好地工作 这就是插件让我包括的内容 include MUI nsh define MUI PAGE CUSTOMFUNCTION SHOW LicenseShow
  • 如何限制循环的迭代次数?

    假设我有一个项目列表 我想迭代其中的前几个 items list range 10 I mean this to represent any kind of iterable limit 5 简单的实现 来自其他语言的 Python 新手可