27

一个关于 Python 语法的简单问题。我想在while循环的条件下将一个值从一个函数分配给一个变量。当函数返回的值为 false 时,循环应该中断。我知道如何在 PHP 中做到这一点。

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

但是,当我在 Python 中尝试类似的语法时,会出现语法错误。

4

4 回答 4

38

2020年答案:

从 Python 3.8 开始,“海象运算符” :=的存在正是您想要的:

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

(如果存在该 fgetcsv 函数)

2013 回答: 你不能在 Python 中做到这一点,在表达式中没有赋值。至少这意味着您不会不小心输入 == 而不是 = 或相反并让它工作。

传统的 Python 风格是只使用 while True 和 break:

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

但现在我把它放在一个生成器中:

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

这样在使用该文件的代码中,丑陋就被隐藏起来了:

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

当然,如果您实际上是在读取 CSV,请使用 csv 模块。

于 2013-11-04T12:45:15.740 回答
37

您不能在表达式中使用赋值。赋值本身就是一个语句,不能组合 Python 语句。

这是语言设计者做出的明确选择;很容易意外使用一个=并分配,而您本来打算使用两个==并测试是否相等。

将赋值移动循环中,或在循环之前赋值,并在循环本身中分配新值。

对于您的特定示例,Pythoncsv模块为您提供了更高级别的 API,而您将循环访问csv.reader()

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

很少(如果有的话)需要在循环构造中分配。通常有一种(很多)更好的方法来解决手头的问题。

也就是说,从 Python 3.8 开始,该语言实际上将具有赋值表达式,:=用作赋值运算符。见PEP 572。赋值表达式实际上在列表推导中很有用,例如,当您需要在正在构建的列表中包含方法返回值并且需要能够在测试中使用该值时。

现在,您必须使用生成器表达式:

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

但使用赋值表达式,您可以内联os.path.abspath()调用:

filtered = [abs for p in files if included(abs := os.path.abspath(p))]
于 2013-11-04T12:40:37.330 回答
4

我写了一个小的 Python 模块,我称之为let,它允许你在任何允许函数的地方执行变量赋值。

像这样安装它:

pip install let

我相信以下内容将完成您正在寻找的内容:

from let import let

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

然而......邓肯的评论说使用的原始问题iter很有趣。在他提出之前我不知道这个功能,现在我相信它可能是比我更好的解决方案。这是有争议的 -iter需要明确提供一个哨兵,而我的并不关心,只是等待fgetcsv返回任何Falsey 值。

于 2016-02-08T02:36:18.493 回答
4

Python 3.8 pep-0572现在使用新符号:=. 看一看 :)

例如:

while chunk := file.read(8192):
   process(chunk)
于 2019-10-13T19:07:37.960 回答