5
\$\begingroup\$

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
\$\endgroup\$
4
\$\begingroup\$

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']:
\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – akaihola Jun 2 '12 at 9:13
  • \$\begingroup\$ @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. \$\endgroup\$ – Brady Jun 2 '12 at 11:15
6
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ I don't think it's necessary to raise a StopIteration explicitly. Maybe just break on "q", else yield. \$\endgroup\$ – akaihola Jun 2 '12 at 9:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.