在Python中的while循环条件中分配变量?


71

我刚刚遇到了这段代码

while 1:
    line = data.readline()
    if not line:
        break
    #...

并且认为,必须有一个比用无限循环更好的方法break

所以我尝试了:

while line = data.readline():
    #...

显然有一个错误。

有什么方法可以避免break在那种情况下使用?

编辑:

理想情况下,您要避免readline重复说两次...恕我直言,重复甚至比a还要糟糕break,尤其是在语句很复杂的情况下。


3
虽然这是一个很好的问题,我认为for line in data解决方案非常适合该特定问题,但我认为该while True: ... break成语没有任何问题。不要害怕。:-)
Kirk Strauser 2011年

4
这些答案在while循环的条件下提供了赋值的替代方法,但实际上并没有回答这个问题:是否可以在while循环中进行赋值?我遇到了同样的问题,尝试同时执行(character = string [i]):我知道for循环是遍历字符串的更好方法,但是我的条件实际上比这复杂得多,并且我想将此赋值作为条件中“或”的右侧进行。

1
@KirkStrauser中断构造的问题在于,它使用四行来表达某些内容,而其他语言则只能在一行中完成。但是,它做对了。到目前为止,没有给出的答案提供了更好的通用解决方案。它们要么只使用迭代器,要么重复分配,这比Break版本的额外三行代码差。
kasperd 2014年

Answers:


29

如果您不对数据做任何奇特的事情,例如以后再阅读更多行,总会有:

for line in data:
    ... do stuff ...

我试图通过考虑一种对象类型来玩“树桩寿司吞噬者”,该对象data可能支持.readline()但不支持__iter __()。我在画空白。你知道有什么坏处吗?
Kirk Strauser 2011年

这不是需要先将整个文件读入内存吗?这似乎不适用于大文件。(特别是如果文件大于您的RAM可以容纳的大小!)
ThorSummoner 2014年

如果data是文件对象(这是一个奇怪的名称,但那是OP使用它的方式),则整个文件将不会被读入内存。 for line in data将遍历行,并根据需要读取它们。
Ned Batchelder 2014年

@NedBatchelder:根据文档在docs.python.org/2/library/stdtypes.html#file.next -和我的不幸经历-文件指针是不是你希望它是(例如,用于data.tell())与for line in data和甚至在读取最后一行之前,它甚至可能位于文件的末尾。因此,如果您要依靠python / os来计算文件中的位置,那么它就不会“按需读取”。
mpag

1
@mpag绝对不能保证(并且我并不是要暗示有这样的意思)每一行都根据需要精确地读取。我反对将整个文件读入内存的想法。如果要逐行迭代,则不能对文件指针的位置做任何假设。
Ned Batchelder

55

从开始Python 3.8,并引入赋值表达式(PEP 572):=运算符),现在可以data.readline()将while循环的条件值()捕获为变量(line),以便在循环体内重复使用它:

while line := data.readline():
  do_smthg(line)


19

这并没有好多少,但这是我通常这样做的方式。Python不会像其他语言(例如Java)那样在变量赋值时返回值。

line = data.readline()
while line:
    # ... do stuff ... 
    line = data.readline()

6
我不是特别喜欢它,尤其是如果... do stuff ...它的大小很大,因为它要求您在破解时牢记整个循环的流程。例如,如果您添加了if line.startswith('foo'): continue后来才意识到的东西line,但直到最后才更新,那么您就无意中创建了一个无限循环。
Kirk Strauser 2011年

1
@Kirk-在某种程度上,我同意,但是替代方案并没有更好。理想情况下,您正在使用的类实现了一个生成器,您可以仅使用for循环,但是在某些情况下,您需要使用while循环(例如,“ while cur_time> expected_time:”)。我不知道OP的职位是否好得多,但我认为这是一个见解的问题:)
dfb

经典的while循环,对于任何质量的程序员都是可以理解的。可能是将来维护目的的最佳选择。

1
@Kirk Strauser一个人可能会争辩说,如果... do stuff ...这么长时间您对循环中发生的事情失去了了解,那么您可能做错了。
arkan

6

喜欢,

for line in data:
    # ...

?它很大程度上取决于data对象的readline语义。如果data是一个file对象,那将起作用。


4
for line in data:
    ... process line somehow....

将遍历中的每一行file,而不是使用while。根据我的经验(在Python中),读取文件的任务是一种更为常见的习惯用法。

实际上,data不必一定是文件,而只需提供一个迭代器。


3

从python 3.8(实现PEP-572)开始,此代码现在有效:

while line := data.readline():
   # do something with line 

2

您可以这样做:

line = 1
while line:
    line = data.readline()

6
这将比预期执行的时间多执行一次循环主体。
kasperd 2014年

2

如果data具有返回迭代器而不是readline(say data.iterate)的函数,则可以简单地执行以下操作:

for line in data.iterate():
    #...

1
除非您知道data它很小(甚至直到那时才知道),否则不要这样做,因为.readlines()会将所有内容都吸收到RAM中,但实际上并不会给您任何回报。
Kirk Strauser 2011年

如果函数返回迭代器而不是整个列表,它应该可以正常工作,对吗?
TorelTwiddler 2011年

是的,但是我还没有看到.readlines()实现这种方式。“ file.readlines()的文档说,它将“直到使用Efreadline()进行EOF并返回包含由此读取的行的列表”。
Kirk Strauser 2011年

我更喜欢那个答案。:-)但是,通常的名称iterate__iter__,然后您可以将循环重写为for line in data
Kirk Strauser 2011年

没错,但是我将这样,因为已经有4个其他答案了for line in data。= D
TorelTwiddler

2

data其他答案所述,如果为文件,for line in file则可以正常使用。如果数据不是文件,而是随机数据读取对象,则应将其实现为迭代器,实现__iter__next方法。

next方法应该读取数据,检查是否有更多数据,如果没有,则引发StopIteration。如果这样做,则可以继续使用该for line in data成语。


2

根据Python文档中的常见问题解答,首选的惯用方法是使用for构造对输入进行迭代或运行无限while True循环并使用break语句终止输入。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.