Python Присвоить значение переменной во время условия while, в то время как Loop

Простой вопрос о синтаксисе Python. Я хочу назначить значение из функции переменной во время условия цикла while. Когда значение, возвращаемое функцией, является ложным, цикл должен прерываться. Я знаю, как это сделать в PHP.

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

Однако, когда я пытаюсь использовать аналогичный синтаксис в Python, я получаю синтаксическую ошибку.

Ответы

Ответ 1

Вы не можете использовать присваивание в выражении. Назначение само по себе является оператором, и вы не можете комбинировать операторы Python.

Это явный выбор, сделанный дизайнерами языка; слишком легко случайно использовать один = и назначить, где вы хотели использовать два == и проверить на равенство.

Переместите присваивание в цикл или присвойте его перед циклом и назначьте новые значения в самом цикле.

В вашем конкретном примере модуль Python csv предоставляет вам высокоуровневый 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))]

Ответ 2

Вы не можете сделать это в Python, без присваивания в выражениях. По крайней мере, это означает, что вы случайно не будете набирать == вместо = или наоборот и будете работать.

Традиционный стиль Python должен использовать только 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.

Ответ 3

Я написал небольшой модуль 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, чтобы вернуть любое значение False y.

Ответ 4

Python 3.8 pep-0572 теперь решает эту проблему, используя новую запись :=. Посмотрите :)

Например:

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