Python 有类似于 for 循环的语法吗(不是 foreach)

13 投票
4 回答
3326 浏览
提问于 2025-04-15 17:18

Python的迭代器虽然很好用,但有时候我真的想要一个像C语言那样的for循环,而不是foreach循环。比如说,我有一个开始日期和一个结束日期,我想对这个范围内的每一天做一些事情。当然,我可以用while循环来实现:

    current = start
    while current <= finish:
        do_stuff(current)
        current += timedelta(1)

这样是可以的,但这需要三行代码,而在C语言或类似的语言中只需要一行。我经常会忘记写增加计数的那一行,尤其是当循环里的内容比较复杂的时候。那么在Python中有没有更优雅、更不容易出错的方法呢?

4 个回答

1

这个方法在紧急情况下可以用:

def cfor(start, test_func, cycle_func):
    """A generator function that emulates the most common case of the C for
    loop construct, where a variable is assigned a value at the begining, then
    on each next cycle updated in some way, and exited when a condition
    depending on that variable evaluates to false. This function yields what
    the value would be at each iteration of the for loop.

    Inputs:
        start: the initial yielded value
        test_func: called on the previous yielded value; if false, the
                   the generator raises StopIteration and the loop exits.
        cycle_func: called on the previous yielded value, retuns the next
                    yielded value
    Yields:
        var: the value of the loop variable

    An example:

    for x in cfor(0.0, lambda x: x <= 3.0, lambda x: x + 1.0):
        print x    # Obviously, print(x) for Python 3

    prints out

    0.0
    1.0
    2.0
    3.0

    """
    var = start
    while test_func(var):
        yield var
        var = cycle_func(var)
2

在Python中,要把事情做得简洁一点并不容易,因为这个语言的一个基本概念就是不能在比较中进行赋值。

对于一些复杂的情况,比如日期,我觉得Ned的回答非常好。但对于简单的情况,我发现itertools.count()这个函数非常有用,它可以返回连续的数字。

>>> import itertools
>>> begin = 10
>>> end = 15
>>> for i in itertools.count(begin):
...   print 'counting ', i
...   if i > end:
...     break
...
counting  10
counting  11
counting  12
counting  13
counting  14
counting  15
counting  16

我觉得这样更不容易出错,因为正如你所说的,容易忘记'current += 1'。对我来说,做一个无限循环,然后检查结束条件似乎更自然。

29

优雅且符合Python风格的做法是把日期范围的概念放在一个自己的生成器里,然后在你的代码中使用这个生成器:

import datetime

def daterange(start, end, delta):
    """ Just like `range`, but for dates! """
    current = start
    while current < end:
        yield current
        current += delta

start = datetime.datetime.now()
end = start + datetime.timedelta(days=20)

for d in daterange(start, end, datetime.timedelta(days=1)):
    print d

输出结果是:

2009-12-22 20:12:41.245000
2009-12-23 20:12:41.245000
2009-12-24 20:12:41.245000
2009-12-25 20:12:41.245000
2009-12-26 20:12:41.245000
2009-12-27 20:12:41.245000
2009-12-28 20:12:41.245000
2009-12-29 20:12:41.245000
2009-12-30 20:12:41.245000
2009-12-31 20:12:41.245000
2010-01-01 20:12:41.245000
2010-01-02 20:12:41.245000
2010-01-03 20:12:41.245000
2010-01-04 20:12:41.245000
2010-01-05 20:12:41.245000
2010-01-06 20:12:41.245000
2010-01-07 20:12:41.245000
2010-01-08 20:12:41.245000
2010-01-09 20:12:41.245000
2010-01-10 20:12:41.245000

这和关于range的回答类似,不过内置的range不能处理日期时间,所以我们需要自己创建一个。不过至少我们可以把这个过程封装起来,只需要做一次。

撰写回答