繁体   English   中英

在python中模拟C风格的循环

[英]Simulating C-style for loops in python

(即使这个标题会导致火焰,我意识到)

Python做出了深思熟虑的设计选择,让for循环使用显式迭代,在大多数情况下,代码大大简化了。

但是,如果你的测试用例和更新函数很复杂,有时候构造一个iterable会很麻烦,所以我发现自己编写了以下while循环:

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

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

  • 使用重复代码进行复杂/ awkard更新,AND

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

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

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

这让我感到震惊,因为waaaaay太冗长和复杂。 堆栈溢出中的人有一个更简单的建议吗?

回复评论:

@Glenn Maynard:是的,我驳回了答案。 如果有一种方法可以在一个方法中编写五行,那就太糟糕了......特别是在一直出现的情况下(循环是图灵完成程序的一个共同特征)。

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

for (date = start; date < end; date = calendar.next_quarter_end(date)):
    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有一个闭包表达式的语法。

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

我有点困惑:你有一个复杂的while表达式,一个复杂的下一个表达式,但它们很适合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...

这似乎是您的日历类提供的一个很棒的抽象,我打赌你会不止一次地使用它。

关于什么:

date = start

while date < end:

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

    date = calendar.next_quarter_end(date)

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

(事实是,由于它们是不同的语言,你不可能将C映射中的每个构造都用于Python中更紧凑的构造。它就像声称有一个压缩算法在所有随机输入上同样有效。)

您可以使用try / finally子句来执行更新:

val = START_VAL

while <awkward/complicated test case>:
    try:
        # do stuff
        continue

    finally:
        val = <awkward/complicated update>

警告:如果你break这也会执行更新语句。

我经常这样做

while True:
   val = <awkward/complicated update>
   if not val:
     break

   etc.

嘿:

def forre(a,i,c,top,increment,run):
    increment = increment.replace("++","+=1").replace("--","-=1").replace("; ","")
    while i != top:
        try: exec(run)
        except: print "error: "; print run
        try: exec(increment)
        except: print "error: "; print increment

forre("int i=",0,"; i<",6,"; i++", 
    "print i"
    )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM