while循环中的小代码冗余(感觉不够简洁)

11

所以,在Python中(尽管我认为它可以应用于许多语言),我经常会遇到以下类似的情况:

the_input = raw_input("what to print?\n")
while the_input != "quit":
    print the_input
    the_input = raw_input("what to print?\n")

也许我太挑剔了,但我不喜欢重复使用 the_input = raw_input("what to print?\n") 这一行。它降低了可维护性和组织性。但是我没有看到任何避免重复代码的解决方法,而且进一步恶化了问题。在某些语言中,我可以写出这样的代码:

while ((the_input=raw_input("what to print?\n")) != "quit") {
    print the_input
}

这明显不符合Python的编程规范,而且据我所知Python甚至不允许在循环条件中进行赋值。

下面这段有效的代码修复了这个重复性问题,

while 1:
    the_input = raw_input("what to print?\n")
    if the_input == "quit":
        break
    print the_input

但这种方法也不太对。使用 while 1 意味着这个循环将永远运行;我在使用循环,但是给它一个虚假的条件,然后把真正的条件放在里面。

我是不是太挑剔了?有没有更好的方法可以做到这一点?也许有一些专门设计用于此的语言结构,我不知道吗?


1
我认为第一种形式是完全可以接受的。 - Robert Harvey
5
这是一个常见的编程模式,叫做“循环和半个”(loop and a half)。 - Matthew Flaschen
1个回答

30

考虑迭代器——例如,在这个具体的情况中:

for the_input in iter(lambda: raw_input('what to print?\n'), 'quit'):
    print the_input

除了在最低层次的抽象中,Python 中的大多数循环都最好使用 for 循环来实现,并借助一些底层迭代器来捕获“循环逻辑”——内置函数 iter 可以帮助实现(如此处所示),有时生成器表达式(genexps)可以,有时标准库模块 itertools 也能解决。

通常您会选择编写定制的 生成器函数(使用 yield 的函数),或者更偶尔会编写自定义的 迭代器类(定义 __iter__ 特殊方法作为 return self,并且定义 next [[或者在最新版本的 Python 中是 __next__]] 来返回“迭代中的下一个值”(the next value from the iteration))。

将循环逻辑与顺序生成的各个项目上执行的任何操作分离开来,是这里的关键抽象助手!


+1:在任何提供它们的语言中,都应优先使用for循环进行迭代。 - johnsyweb
这是一个惊人的解决方案。不过,SO还需要4分钟才能让我接受答案;-) - Ponkadoodle
@Robert,为什么说“太聪明了”?这是在Python中执行应用程序级别循环的最佳方式——将循环逻辑(如何启动循环下一个步骤以及何时决定循环完成)与应用程序逻辑(对于每个循环步骤的结果要做什么)分离开来。像iter这样的内置函数、像itertools这样的标准库模块、像生成器和生成式这样的整个语言结构,本质上都是为了支持这种关键的风格选择,而你却认为它“太聪明了”!请问您能否详细阐述一下您简短的批评的原因...? - Alex Martelli
@wallacoloo,没问题,我会耐心等待4分钟的;-)。 - Alex Martelli
1
我确实喜欢使用iter(callable, sentinel)(以前不知道),但我不太喜欢使用lambda(虽然我不指望你为这样一个小例子定义一个函数)(我只是想看到"for line in iter(prompt, 'quit'):"的样子)。 - Terence Honles
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接