惯用的 Python:'times' 循环

Posted

技术标签:

【中文标题】惯用的 Python:\'times\' 循环【英文标题】:Idiomatic Python: 'times' loop [duplicate]惯用的 Python:'times' 循环 【发布时间】:2011-02-09 01:37:35 【问题描述】:

假设我有一个函数foo,我想调用n 次。在 Ruby 中,我会写:

n.times  foo 

在 Python 中,我可以这样写:

for _ in xrange(n): foo()

但这似乎是一种老套的做事方式。

我的问题:在 Python 中有没有一种惯用的方式来做到这一点?

【问题讨论】:

不要忘记 ruby​​ 也会计算循环的计数器变量。特别是 n.times|i|富。在您的情况下,您只是将其丢弃。那么为什么这在 ruby​​ 中可以,但在 python 中是 hacky 呢? 因为我不必明确地扔掉它。 :-) Ruby 版本也更好地展示了该行的意图,IMO。 我使用 x 作为丢弃变量,但 _ 似乎更惯用。是的,python 没有times 函数.. @perimosooriade 如果您担心向其他 Python 开发人员清楚地“展示您的意图”,_ 是您的最佳选择。 @drozzy ruby​​ 块不强制执行 arity 的部分原因是,您可以完全按照本例中的方式丢弃变量——它不会影响性能,而且是惯用的。没什么可笑的。 【参考方案1】:

问题的前提是调用 foo() n 次是先验必要的事情。 n 是从哪里来的?它是可迭代的东西的长度吗?然后遍历可迭代对象。当我开始使用 Python 时,我发现我几乎没有使用任意值;你的 n 背后有一些更重要的含义,当它变成一个整数时就丢失了。

今天早些时候,我偶然发现了 Nicklaus Wirth 为 IEEE 计算机 撰写的题为 Good Ideas - Through the Looking Glass(存档 version 供未来读者使用)的具有挑战性的论文。在第 4 节中,他对每个人(包括他自己)都认为理所当然但存在表达缺陷的编程结构提出了不同的看法:

"Algol 的一般性for 声明应该是一个警告 向所有未来的设计师发出信号 始终保持一个主要目的 构想,厌倦 夸大了一般性和复杂性, 这很容易变成 适得其反。”

algol for 等同于 C/Java for,只是做得太多了。那篇论文是一本有用的读物​​,因为它使人们不会像我们那么容易做的那样认为理所当然。所以也许一个更好的问题是“为什么需要一个执行任意次数的循环?”

【讨论】:

您是对的,很少有需要这样做的情况。不过有一些。就我而言,在读取数据之前,我需要在文件中跳过一定数量的行。此外,基准测试代码往往需要任意数量的运行。影响某些全局状态(如 IO 操作)的事情是最常见的罪魁祸首。 如果你想从一个文件中跳过一定数量的行,你可以使用: next(itertools.islice(thefile, n-1, n)) 这有速度的优势,虽然它缺乏for 循环的清晰度。 遗憾的是,这些 IEEE 链接现在已断开。该文章可供订阅者或购买,地址为computer.org/portal/web/csdl/doi/10.1109/MC.2006.20。 @perimosocordiae:你可以使用consume() itertools' recipe: next(islice(file, n, n), None)跳过文件中的n 我同意这种观点,但我只是不明白这如何回答这个问题......【参考方案2】:

如果你想要times 方法,并且你需要在你自己的函数中使用它,试试这个:

def times(self, n, *args, **kwargs):
    for _ in range(n):
        self.__call__(*args, **kwargs)

import new
def repeatable(func):
    func.times = new.instancemethod(times, func, func.__class__)
    return func

现在将@repeatable 装饰器添加到您需要times 方法的任何方法:

@repeatable
def foo(bar):
    print bar

foo.times(4, "baz") #outputs 4 lines of "baz"

【讨论】:

【参考方案3】:

你已经展示了惯用的方式:

for _ in range(n): # or xrange if you are on 2.X
    foo()

不确定这有什么“骇人听闻的”。如果您有更具体的用例,请提供更多详细信息,可能会有更适合您正在做的事情。

【讨论】:

我只认为它很hackish,因为它生成的范围值我用 _ 约定丢弃了。出于某种原因,我似乎在回避。 这就是您使用_ 而不是其他名称的原因。它的意思是“丢弃变量”——_ 被丢弃的想法在 Python、Prolog、Haskell 以及可能的其他一些语言中很常见。 range 不是低效的,因为它使用 n 字节的内存作为计数器,而 C for 循环将只使用一个字节作为计数器? +1 供_使用,不知道那个! 这应该是公认的答案。【参考方案4】:

最快、最干净的是itertools.repeat:

import itertools

for _ in itertools.repeat(None, n):
    foo()

【讨论】:

这并没有摆脱未使用的变量。 我计时了几种方法,其中 itertools 比 xrange 快 50%。不过,我不会说它更干净。 @dan04,什么“未使用的变量”——_?! Puh-Leahze!-)

以上是关于惯用的 Python:'times' 循环的主要内容,如果未能解决你的问题,请参考以下文章

python循环嵌套的几种使用方法

F# 惯用的 async while 循环累加转换

处理在多个 for 循环中声明的变量的最惯用方法是啥? [关闭]

使用传递值运行嵌套循环的惯用方式

在像python time.time()这样的javascript中获取时间[重复]

有没有更惯用的方式来表达我的循环中还剩下多少次迭代?