Как сделать присвоение переменной внутри цикла while (expression) в Python? - PullRequest
15 голосов
/ 12 февраля 2009

У меня есть присвоение переменной, чтобы вернуть назначенное значение и сравнить его с пустой строкой непосредственно в цикле while.

Вот как я делаю это в PHP:

while((name = raw_input("Name: ")) != ''):
    names.append(name)

То, что я пытаюсь сделать, идентично этому по функциональности:

names = []
while(True):
    name = raw_input("Name: ")
    if (name == ''):
        break
    names.append(name)

Есть ли способ сделать это в Python?

Ответы [ 6 ]

15 голосов
/ 13 февраля 2009
from functools import partial

for name in iter(partial(raw_input, 'Name:'), ''):
    do_something_with(name)

или если вы хотите список:

>>> names = list(iter(partial(raw_input, 'Name: '), ''))
Name: nosklo
Name: Andreas
Name: Aaron
Name: Phil
Name: 
>>> names
['nosklo', 'Andreas', 'Aaron', 'Phil']
13 голосов
/ 12 февраля 2009

Вы можете обернуть raw_input(), чтобы превратить его в генератор:

def wrapper(s):
    while True:
        result = raw_input(s)
        if result = '': break
        yield result

names = wrapper('Name:')

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

9 голосов
/ 12 февраля 2009

Нет, извините. Это часто задаваемые вопросы, хорошо объяснил здесь:

В Пидоки и блог Фредрика Лунда .

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

Многие альтернативы были предложены. Большинство из них - это хаки, которые сохраняют некоторую типизацию, но используют произвольный или загадочный синтаксис или ключевые слова и не соответствуют простому критерию предложений по изменению языка: он должен интуитивно подсказывать правильное значение человеку, который еще не знаком с конструкцией.

Интересным явлением является то, что большинство опытных программистов на Python распознают идиому while True и, похоже, не слишком упускают присваивание в конструкции выражения; только новички выражают сильное желание добавить это к языку.

Есть альтернативный способ написания этого, который кажется привлекательным:

line = f.readline() while line:
    ... # do something with line...
    line = f.readline()
1 голос
/ 13 апреля 2015
names = []
for name in iter(lambda: raw_input("Name: "), ''):
    names.append(name)
1 голос
/ 16 мая 2013

Я опоздал всего на 7 лет, но есть другое решение. Это не лучшее решение, которое я могу придумать, но оно подчеркивает интересное использование исключения StopItered. Вы можете сделать аналогичный цикл для чтения файлов / сокетов и обрабатывать тайм-ауты и так далее.

names=[]
try:
    while True:
        f = raw_input()
        if not f:
            raise StopIteration
        else:
            names.append(f)
except StopIteration:
    pass

print names
0 голосов
/ 09 октября 2018

PEP 572 предлагает Выражения назначения и уже принято. Начиная с Python 3.8, вы сможете написать:

while name := input("Name: "):
    names.append(name)

Цитирование Синтаксиса и семантики части PEP для некоторых других примеров:

# Handle a matched regex
if (match := pattern.search(data)) is not None:
    # Do something with match

# A loop that can't be trivially rewritten using 2-arg iter()
while chunk := file.read(8192):
   process(chunk)

# Reuse a value that's expensive to compute
[y := f(x), y**2, y**3]

# Share a subexpression between a comprehension filter clause and its output
filtered_data = [y for x in data if (y := f(x)) is not None]
...