Python While循环中的赋值条件

41

C语言中,可以进行以下操作:

while( (i=a) != b ) { }

但在Python中似乎是不行的。

while (i = sys.stdin.read(1)) != "\n":

生成

    while (i = sys.stdin.read(1)) != "\n":
         ^
SyntaxError: invalid syntax

(^ 应该在 = 上方)

有什么解决方法吗?


哦,那有点尴尬... readline()raw_input() 有什么区别? - tekknolagi
1
@tekknolagi 他可能没有收到你的评论。在评论文本中添加“@名称”来提醒某个人是一个好主意。 - ovgolovin
@JochenRitzel 看到我的评论了吗?抱歉 :) - tekknolagi
1
这在Python中不起作用的原因是赋值是“语句”而不是“表达式” - 这仅仅是由于语法产生规则所致。 - user166390
1
请参阅Python常见问题解答,了解为什么不能在表达式中使用赋值操作符的解释:为什么我不能在表达式中使用赋值操作符?。它提倡使用迭代器或while True来替代。 - Trevor Robinson
显示剩余2条评论
5个回答

41

Python 3.8 开始,并引入了 赋值表达式(PEP 572):= 操作符),现在可以将表达式值(此处为 sys.stdin.read(1))捕获为变量,以便在 while 循环体内使用:

while (i := sys.stdin.read(1)) != '\n':
  do_smthg(i)

这段代码:

  • sys.stdin.read(1)的结果赋值给变量i
  • 比较i\n
  • 如果条件成立,进入while循环体中,可以使用i

1
是的,谢谢!这里最佳答案。 - David Hempy

27

使用 break 关键字:

while True:
    i = sys.stdin.read(1)
    if i == "\n":
       break
    # etc...

4
对我来说,这似乎是一个非常合理的模式。循环在哪里中断并不重要,终止条件会发生或者不会发生。如果i == "\n"没有在循环内发生(导致退出循环),它也不会在 while 循环的条件中发生。 - vastlysuperiorman

9
您可以使用内置函数 iter() 并进行双参数调用来完成此操作:
import functools
for i in iter(fuctools.partial(sys.stdin.read, 1), '\n'):
    ...

相关文档:

iter(o[, sentinel])
...
如果给出第二个参数 sentinel,则 o 必须是一个可调用对象。在这种情况下创建的迭代器将对其 next() 方法的每次调用调用 o,如果返回的值等于 sentinel,则会引发 StopIteration,否则将返回该值。

使用 iter() 的第二种形式的一个有用应用程序是读取文件的行,直到达到某一行。以下示例读取文件,直到 readline() 方法返回空字符串为止:

with open('mydata.txt') as fp:
    for line in iter(fp.readline, ''):
        process_line(line)

8
没有使用 functools 的版本:
for i in iter(lambda: sys.stdin.read(1), '\n'):

3

我个人喜欢imm和Mark的答案,他们使用了break,但你也可以这样做:

a = None
def set_a(x):
    global a
    a = x
    return a

while set_a(sys.stdin.read(1)) != '\n':
    print('yo')

虽然我不建议这样做。

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