How to do variable assignment inside a while(expression) loop in Python?
Asked Answered
D

6

15

I have the variable assignment in order to return the assigned value and compare that to an empty string, directly in the while loop.

Here is how I'm doing it in PHP:

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

What I'm trying to do is identical to this in functionality:

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

Is there any way to do this in Python?

Directly answered 12/2, 2009 at 16:44 Comment(0)
V
15
from functools import partial

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

or if you want a list:

>>> names = list(iter(partial(raw_input, 'Name: '), ''))
Name: nosklo
Name: Andreas
Name: Aaron
Name: Phil
Name: 
>>> names
['nosklo', 'Andreas', 'Aaron', 'Phil']
Valerivaleria answered 13/2, 2009 at 2:58 Comment(1)
Not an answer; I still don't know: do you bind a variable in a while in Python?Simian
E
13

You can wrap raw_input() to turn it into a generator:

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

names = wrapper('Name:')

which means we're back to square one but with more complex code. So if you need to wrap an existing method, you need to use nosklo's approach.

Enneagon answered 12/2, 2009 at 16:49 Comment(8)
+1: Beat me by seconds. Please add the definition of "raw_input as generator" to your answer, though.Grivet
Cool thanks! First time using stack overflow btw, never knew it was this awesome, a perfect answer within minutes :)Directly
Can you detail how to "turn raw_input into a generator" in a very pythonic way?Yocum
do you turn it to a generator or use it as a generator? btw nice answer, didn't you know raw_input can be used that way :)Woodborer
This solution will assign a list of characters in the first response to names. It's incorrect.Almanza
recursive is right. Nosklo's answer below is correct: iter() will run until '' is reached, and then list() will converts each iteration to an element.Oquendo
@recursive: Sorry, didn't realize that raw_input() was an existing method. I assumed that it was something Andreas had written.Enneagon
Thanks. I deleted my comments and will delete this one.Gromwell
B
9

No, sorry. It's a FAQ, explained well here:

In Pydocs, and Fredrik Lundh's blog.

The reason for not allowing assignment in Python expressions is a common, hard-to-find bug in those other languages.

Many alternatives have been proposed. Most are hacks that save some typing but use arbitrary or cryptic syntax or keywords, and fail the simple criterion for language change proposals: it should intuitively suggest the proper meaning to a human reader who has not yet been introduced to the construct.

An interesting phenomenon is that most experienced Python programmers recognize the while True idiom and don’t seem to be missing the assignment in expression construct much; it’s only newcomers who express a strong desire to add this to the language.

There’s an alternative way of spelling this that seems attractive:

line = f.readline() while line:
    ... # do something with line...
    line = f.readline()
Bolzano answered 12/2, 2009 at 16:48 Comment(1)
this link appears to be brokenMimimimic
B
1

I'm only 7 years late, but there's another solution. It's not the best solution I can think of, but it highlights an interesting use of the StopIteration exception. You can do a similar loop for chunk reading files/sockets and handle Timeouts and whatnot nicely.

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

print names
Beach answered 15/5, 2013 at 22:23 Comment(0)
S
1
names = []
for name in iter(lambda: raw_input("Name: "), ''):
    names.append(name)
Schmit answered 13/4, 2015 at 11:45 Comment(0)
M
1

PEP 572 proposes Assignment Expressions and has already been accepted. Starting with Python 3.8, you will be able to write:

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

Quoting the Syntax and semantics part of the PEP for some more examples:

# 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]
Marino answered 9/10, 2018 at 14:8 Comment(1)
I use this all the time and discovered this by accident with trial and error. Although this works with Python, Cython doesn't recognize this and throws an error. Error compiling Cython file: ------------------------------------------------------------ ... while my_var := "".join( ^ ------------------------------------------------------------Entomologize

© 2022 - 2024 — McMap. All rights reserved.