简体   繁体   English

Python 在 while 循环中的条件期间为变量赋值

[英]Python Assign value to variable during condition in while Loop

A simple question about Python syntax.关于 Python 语法的一个简单问题。 I want to assign a value from a function to a variable during the condition for a while loop.我想在 while 循环的条件期间将一个函数的值分配给一个变量。 When the value returned from the function is false, the loop should break.当函数返回的值为 false 时,循环应该中断。 I know how to do it in PHP.我知道如何在 PHP 中做到这一点。

while (($data = fgetcsv($fh, 1000, ",")) !== FALSE) 

However when I try a similar syntax in Python I get a syntax error.但是,当我在 Python 中尝试类似的语法时,出现语法错误。

You cannot use assignment in an expression.不能在表达式中使用赋值。 Assignment is itself a statement, and you cannot combine Python statements.赋值本身就是一个语句,不能组合 Python 语句。

This is an explicit choice made by the language designers;这是语言设计者做出的明确选择; it is all too easy to accidentally use one = and assign, where you meant to use two == and test for equality.很容易不小心使用一个=并赋值,而您打算使用两个==并测试相等性。

Move the assignment into the loop, or assign before the loop, and assign new values in the loop itself.将赋值移到循环中,或循环之前赋值,并在循环本身中赋值新值。

For your specific example, the Python csv module gives you a higher-level API and you'd be looping over the csv.reader() instead:对于您的具体示例,Python csv模块为您提供了一个更高级别的 API,而您将在csv.reader()循环:

with open(csvfilename, 'rb') as csvfh:
    reader = csv.reader(csvfh)
    for row in reader:

I rarely , if ever, need to assign in a loop construct.很少(如果有的话)需要在循环结构中进行分配。 Usually there is a (much) better way of solving the problem at hand.通常有一种(好得多)更好的方法来解决手头的问题。

That said, as of Python 3.8 the language will actually have assignment expressions, using := as the assignment operator.也就是说,从 Python 3.8 开始,该语言实际上将具有赋值表达式,使用:=作为赋值运算符。 See PEP 572 .参见PEP 572 Assignment expressions are actually useful in list comprehensions, for example, when you need to both include a method return value in the list you are building and need to be able to use that value in a test.赋值表达式在列表推导中实际上很有用,例如,当您需要在正在构建的列表中包含一个方法返回值并且需要能够在测试中使用该值时。

Now, you'd have to use a generator expression:现在,您必须使用生成器表达式:

absolute = (os.path.abspath(p) for p in files)
filtered = [abs for abs in absolute if included(abs)]

but with assignment expressions you can inline the os.path.abspath() call:但是使用赋值表达式,您可以内联os.path.abspath()调用:

filtered = [abs for p in files if included(abs := os.path.abspath(p))]

2020 answer: 2020 答案:

Since Python 3.8, the "walrus operator" := exists that does exactly what you want:从 Python 3.8 开始, “海象运算符” :=存在,它完全符合您的要求:

while data := fgetcsv(fh, 1000, ",") != False:
    pass

(if that fgetcsv function existed) (如果存在 fgetcsv 函数)

2013 answer: You can't do that in Python, no assignment in expressions. 2013 年答案:您不能在 Python 中做到这一点,表达式中没有赋值。 At least that means you won't accidentally type == instead of = or the other way around and have it work.至少这意味着您不会意外地键入 == 而不是 = 或相反地使其工作。

Traditional Python style is to just use while True and break:传统的 Python 风格只是使用 while True 和 break:

while True:
    data = fgetcsv(fh, 1000, ",")
    if not data:
        break
    # Use data here

But nowadays I'd put that in a generator:但现在我把它放在一个发电机中:

def data_parts(fh):
    while True:
        data = fgetcsv(fh, 1000, ",")
        if not data:
            break
        yield data

so that in the code that uses the file, the ugliness is hidden away:这样在使用该文件的代码中,丑陋就被隐藏了:

for data in data_parts(fh):
    # Use data here

Of course if it's actually CSV reading that you're doing, use the csv module.当然,如果它实际上是您正在执行的 CSV 读取,请使用 csv 模块。

I wrote a little Python module, which I call let , which allows you to perform a variable assignment anywhere that a function is allowed.我写了一个小的 Python 模块,我称之为let ,它允许你在允许函数的任何地方执行变量赋值。

Install it like this:像这样安装它:

pip install let

I believe the following will accomplish what you're looking for:我相信以下将完成您正在寻找的内容:

from let import let

while let(data = fgetcsv(fh, 1000, ',')):
    # Do whatever you'd like with data here

However... Duncan's comment the original question saying to use iter is interesting.但是...... Duncan 的评论说使用iter的原始问题很有趣。 I wasn't aware of the function until he brought it up, and I now believe it may be a better solution than mine.直到他提出这个功能我才意识到它,现在我相信它可能是比我更好的解决方案。 It's debatable - iter requires a sentinel to be explicitly provided, whereas mine doesn't care and simply waits for fgetcsv to return any False y value.这是有争议的 - iter需要明确提供一个哨兵,而我的不在乎,只是等待fgetcsv返回任何False y 值。

Python 3.8 pep-0572 now address this case using the new notation := . Python 3.8 pep-0572现在使用新符号:=解决这种情况。 Have a look :)看一看 :)

For example:例如:

while chunk := file.read(8192):
   process(chunk)

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

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