# Reading a controll character in a loop in Python [closed]

I have a code snippet below and because of habit from other programming languages I wanted to use a do-while loop instead. But Python offers only the construct which I show as a second code snippet instead of a do-while*loop. What is the best pythonic way to code this?

ch = getch()
while ch != "q":
do_something()
ch = getch()

while True:
ch = getch()
do_something()
if ch == "q":
break


I found a way to do this with Python List Comprehension (chapter 5.1.4) as follows:

(Notice that I used sys.stdin.read(1) instead of getch())

>>> import sys
>>> while [x for x in sys.stdin.read(1) if x != 'q']:
...   print x  # substitute this with your do_something()
...

a
a

b
b

c
c

q
>>>


You could also use, which is a bit uglier to me:

>>> while [] != [x for x in sys.stdin.read(1) if x != 'q']:

• Both of these are neat hacks, but the fact that 'x' is visible outside the list comprehension is arguably a wart in Python. I think that both alternatives in the original question express the intent better. – akaihola Jun 2 '12 at 9:13
• @akaihola, ya when I was playing around with it, I was surprised I could get at 'x'. I'll try to think of another alternative that returns and uses a list instead, thanks. – Brady Jun 2 '12 at 11:15

Another way would be using a generator expression. This has the effect of separating the 'control logic' and the 'action logic' (and are extremely useful!).

def getchar_until_quit():
while True:
ch = getch()
if ch != "q":
yield ch
else:
raise StopIteration

for ch in getchar_until_quit():
do_something()
do_something() # to process the 'q' at the end

• I don't think it's necessary to raise a StopIteration explicitly. Maybe just break on "q", else yield. – akaihola Jun 2 '12 at 9:16