在python中模拟C风格的循环

2024-05-15 12:45:42 发布

您现在位置:Python中文网/ 问答频道 /正文

(我意识到,即使这个标题也会引起火灾)

Python做了一个深思熟虑的设计选择,让for循环使用显式iterables,这在大多数情况下都有相当简化的代码的好处。

但是,如果您的测试用例和更新函数很复杂,有时构建iterable是一件很痛苦的事情,因此我发现自己编写了以下while循环:

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

问题在于更新位于while块的底部,这意味着如果我想在其中嵌入continue,我必须:

  • 对复杂的/awkard更新使用重复的代码,然后

  • 冒着忘记它和让我的代码无限循环的风险

我可以手动滚动一个复杂的迭代器:

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

我觉得这太冗长和复杂了。堆栈溢出中的人有更简单的建议吗?

回复评论:

@Glenn Maynard:是的,我拒绝回答。如果有办法一行写五行是不好的。。。尤其是在经常出现的情况下(循环是图灵完整程序的一个常见特性)。

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

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

Tags: 代码testfordate情况updatevaldo
3条回答

我有点困惑:你有一个复杂的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...

这对于您的日历类来说似乎是一个很好的抽象,我打赌您将不止一次地使用它。

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

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有一个用于closured表达式的语法。

编辑:另外,请注意,您只需定义一次cfor(而不是您的complicated_iterator函数)。

怎么办:

date = start

while date < end:

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

    date = calendar.next_quarter_end(date)

但是,如果经常使用那个特定的构造,那么最好只定义一次生成器,然后像在问题中那样重新使用它。

(事实是,因为它们是不同的语言,所以不可能让C中的每个构造都映射到Python中更紧凑的构造。这就像声称有一种压缩算法,它对所有随机输入都同样有效。)

相关问题 更多 >