【问题标题】:Python equivialent of C programming techniques (while loops)Python 等效于 C 编程技术(while 循环)
【发布时间】:2011-06-21 14:41:38
【问题描述】:

在C编程语言中,我经常做以下事情:

while ((c = getch()) != EOF) {
 /* do something with c */
}

在 Python 中,我没有发现任何类似的东西,因为我不允许在计算表达式中设置变量。我通常最终不得不设置两次评估表达式!

c = sys.stdin.read(1)
while not (c == EOF):
 # Do something with c
 c = sys.stdin.read(1)

在我尝试找到更好的方法时,我发现了一种只需要设置和评估一次表达式的方法,但这越来越难看...

while True:
 c = sys.stdin.read(1)
 if (c == EOF): break
 # do stuff with c

到目前为止,对于某些情况,我已经解决了以下方法,但这对于常规的 while 循环来说远非最佳...:

class ConditionalFileObjectReader:
 def __init__(self,fobj, filterfunc):
  self.filterfunc = filterfunc
  self.fobj = fobj
 def __iter__(self):
  return self
 def next(self):
  c = self.fobj.read(1)
  if self.filterfunc(c): raise StopIteration
  return c

for c in ConditionalFileObjectReader(sys.stdin,lambda c: c == EOF):
 print c

我解决一个简单的基本编程问题的所有解决方案都变得太复杂了...... 有没有人建议如何以正确的方式做到这一点?

【问题讨论】:

标签: python c


【解决方案1】:

您通常会在 Python 中使用 for 循环:

for c in sys.stdin.read():
    # whatever

如果您不想一次将整个 stdin 缓冲到内存中,您也可以自己添加一些缓冲,使用较小的缓冲区。

请注意,常量 EOF 在 Python 中不存在。如果流中没有数据,read() 将简单地返回一个空字符串。

【讨论】:

  • 很好,但这并不能解决python中while循环的基本丑陋问题。从标准输入读取只是作为这个“问题”经常发生的例子。
  • @Dog eat cat world:那么在 Python 中对于不需要 while 循环的东西不要使用 while 循环。
  • @Dog: while 循环在 Python 中比在 C 中少得多。而且我个人认为循环中间的中断条件并不难看——它们也经常出现在 C 中.
  • 这不仅仅是一次在内存中缓冲整个输入的问题,read 会阻塞直到有足够的数据可用或 EOF。我们是否肯定地说 Python 没有 方法可以编写比 while True ... break 更好的流式 I/O 循环?我个人可以接受,但我明白为什么人们可能更喜欢“更清洁”的选择。
  • @Dog 你没有要求解决“python中while循环的基本丑陋”。您要求“正确的方法”。在 Python 中你不经常看到 while 循环是有原因的:原因是它们很少是最明显的正确方法。
【解决方案2】:

我相信您想要做的是利用iter 函数。

for c in iter(getch, EOF):
     #inner loop

Iter 是一个非常通用的函数。在这种情况下,您告诉它在每个循环的顶部重复调用 getch(不带参数),直到 getch 返回标记值 EOF。

【讨论】:

  • 谢谢,这也有效。我用 lambda: sys.stdin.read(1) 替换了 getch 但这个问题是针对一般的 while 语法丑陋的,并不局限于这个特定的问题。但我看到了尽可能使用迭代器的意义:)
  • @Brendan:是functools.partial(),我认为不会更快(未测试)。
  • 糟糕。我的印象是lambas在python中相当慢,所以partial可能会更好。
【解决方案3】:

考虑到 EOF 似乎是您关心的,而不是任何任意条件,可以编写更简单的代码来代替 ConditionalFileObjectReader:

def readbytes(file):
    while True:
        c = file.read(1)
        if c == '':
            return
        yield c

for c in readbytes(sys.stdin):
    print c

所以你仍然有'while True ... break',这似乎是 Python[*] 中的首选循环,但至少你只有一次来解决整个问题,“如何迭代类似文件的对象中的字节而不阻塞/缓冲每一行”,并且您将它放在一个不“用 c 做东西”的短循环中 - 这是一个单独的问题。

受 Wallacoloo 的 iter 示例的启发,与上面类似,您可以生成比 iter 更通用的东西:

def until(nextvalue, pred):
    while True:
        value = nextvalue()
        if pred(value):
            return
        yield value

for c in until(lambda: sys.stdin.read(1), lambda x: x == ''):
    print c

我不确定我是否喜欢这个,但可能值得一玩。它试图解决一般问题“迭代某个函数的返回值,直到返回值满足某个条件”。

[*] 我敢说,Pythonic 等价于其他语言的花哨循环语法吗?

【讨论】:

    猜你喜欢
    • 2015-08-09
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多