I'm writing a twirling cursor, which is a cursor that twirls in place in the console. In Forth, this takes just 3 lines, whereas in Python3 I have this:
from time import sleep # sleep(sec)
import sys
def flash(c):
"""Shows character c momentarily."""
# backspace (8ドル) and sleep(sec) keep it in place and slow enough to see
print(c,end=""); sys.stdout.flush(); sleep(0.05); print(chr(0x8),end=""); sys.stdout.flush()
return
def halftwirl():
"""Twirls the cursor in place half-way i.e. | / - \."""
flash(chr(0x7C)); flash(chr(0x2F)); flash(chr(0x2D)); flash(chr(0x5C));
return
def twirl(n):
"""Twirls cursor in place n times."""
for i in range(2*n):
halftwirl()
return
# Programme
print(twirl.__doc__)
twirl(5)
Whilst this works, and is no different from Forth in terms of code structure (see the Forth below), it is still, to my eyes, quite verbose.
In Forth, where there is no expense in calling subroutines, one naturally does something like this:
\ Building Blocks 0x7C constant .| 0x2F constant ./ 0x2D constant .- 0x5C constant .\ 0x8 constant .del \ backspace delete : flash ( c -- ) emit 50 ms .del emit ; \ show character momentarily : half-twirl ( -- ) .| flash ./ flash .- flash .\ flash ; \ half-twirl cursor in place : twirl ( n -- ) 0 do half-twirl half-twirl loop ; \ twirl cursor in place n times
Questions:
Is the cost of calling subroutines in Python cheap enough to support refactoring, i.e. pulling out
flash()
as its own subroutine,halftwirl()
as its own, and makingtwirl()
call these within its inner loop?Is the resulting verbosity as compared to similarly factored Forth code just the cost of doing business when writing in Python compared to Forth, or am I missing some Python idioms?
1 Answer 1
Repetitive code should be put in a loop.
Most programmers don't have the ASCII table memorized. Why not use literal characters instead?
Flush can be handled by print()
itself. I don't believe you need to flush after backspacing.
The speed of the rotation can be made overridable with a trivial change.
from time import sleep
def halftwirl(delay=0.05):
"""Twirls the cursor in place half-way i.e. | / - \."""
for glyph in '|/-\\':
print(glyph, end='', flush=True)
sleep(delay) # sleep(sec) to keep it slow enough to see
print('\b', end='') # backspace to keep it in place
To answer your questions:
- Performance is just not an issue here. The main slowdowns would be the deliberate
sleep()
call and I/O overhead. - See the rewrite above.
-
3\$\begingroup\$ The string constant would look nicer if written
r'|/-\'
. \$\endgroup\$Gareth Rees– Gareth Rees2014年02月03日 18:47:02 +00:00Commented Feb 3, 2014 at 18:47
None
by default, so unless you are planning on returning a value, don't include a return statement. \$\endgroup\$print(c,end=""); sys.stdout.flush(); sleep(0.05); print(chr(0x8),end=""); sys.stdout.flush()
is not clear at all. \$\endgroup\$