在Python中模拟C风格的for循环

23 投票
6 回答
10041 浏览
提问于 2025-04-15 22:10

(我知道这个标题可能会引起争议)

Python在设计上选择让for循环使用明确的可迭代对象,这样在大多数情况下代码会变得简单很多。

不过,有时候如果你的测试案例和更新函数比较复杂,构造一个可迭代对象就会变得很麻烦,因此我发现自己写了以下的while循环:

val = START_VAL
while <awkward/complicated test case>:
    # do stuff
    ...
    val = <awkward/complicated update>

这样做的问题在于,更新的代码放在while块的底部,这意味着如果我想在其中某个地方使用continue,我就必须:

  • 重复写复杂或尴尬的更新代码,另外

  • 还要冒着忘记这部分代码的风险,导致我的代码进入无限循环

我可以选择手动创建一个复杂的迭代器:

def complicated_iterator(val):
    while <awkward/complicated test case>:
         yeild val
         val = <awkward/complicated update>

for val in complicated_iterator(start_val):
    if <random check>:
         continue # no issues here
    # do stuff

但我觉得这样写太冗长和复杂了。Stack Overflow上的朋友们有没有更简单的建议?

对评论的回应:

@Glenn Maynard:是的,我忽略了那个答案。如果有办法用一行代码完成的事情,写五行是很糟糕的……特别是在这种经常出现的情况下(循环是图灵完备程序的常见特征)。

对于那些寻找具体例子的人:假设我在使用一个自定义的日期库。我的问题是,如何用Python表达这个:

for (date = start; date < end; date = calendar.next_quarter_end(date)):
    if another_calendar.is_holiday(date):
       continue
    # ... do stuff...

6 个回答

4

那这样怎么样:

date = start

while date < end:

    if not another_calendar.is_holiday(date):
        # ... do stuff...

    date = calendar.next_quarter_end(date)

不过,如果你经常使用那种特定的写法,最好还是先定义好这个生成器,然后像你在问题中那样重复使用它。

实际上,因为这两种语言不同,你不可能把C语言中的每一种写法都对应到Python中更简洁的写法。这就像说你有一种压缩算法,可以对所有随机输入都一样有效。

6

我有点困惑:你有一个复杂的 while 表达式,还有一个复杂的 next 表达式,但它们却能很好地适应 C 语言的 for 循环?这让我觉得不太合理。

我建议你使用自定义迭代器的方法。你可能会发现迭代器还有其他用处,而且把迭代过程封装起来也是一种很好的编程习惯。

更新:根据你的例子,我肯定会制作一个自定义迭代器。对我来说,日历能够生成一系列季度日期是非常自然的事情:

class Calendar:
    # ...

    def quarters(self, start, end):
        """Generate the quarter-start dates between `start` and `end`."""
        date = start
        while date < end:
            yield date
            date = self.next_quarter_end(date)


for date in calendar.quarters(start, end):
    if another_calendar.is_holiday(date):
       continue
    # ... do stuff...

这看起来是你日历类提供的一个很棒的抽象,我敢打赌你会不止一次用到它。

30

这是我能想到的最好办法:

def cfor(first,test,update):
    while test(first):
        yield first
        first = update(first)

def example(blah):
    print "do some stuff"
    for i in cfor(0,lambda i:i<blah,lambda i:i+1):
        print i
    print "done"

我希望Python能有一种闭包表达式的语法。

编辑:另外,注意你只需要定义一次cfor(而不是你那个complicated_iterator函数)。

撰写回答