[Tutor] TimeTracker [revising Python code]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Tue, 6 Aug 2002 14:41:44 -0700 (PDT)


Hi Kyle,

One other comment about your code:


> #! C:\Python22\python
>
> import time, sys
>
> def sleep(a):
>     currtime = time.strftime( "%I:%M:%S%p %Z" )
>     print "Current time:  %(currtime)s" % vars()
>
>     begin = raw_input( "Begin tracking?  [Y/N]:  " )
>
>     if begin.lower() in "y yes".split():
>         logcurrtime = open( "log.dat", "aa" )
>         logcurrtime.write( " [Current Time:  %(currtime)s]" % vars() )
>         logcurrtime.close()
>
>         int (a)
>         sleeptime = a * 60
>         int (sleeptime)
>
>         logsleeptime = open( "log.dat", "aa" )
>         logsleeptime.write( " [Sleep Time:  %(sleeptime)s Mins.]" %
>         vars() )
>         logsleeptime.close()
>
>         time.sleep( sleeptime )
>         print "Set Time Complete"
>
>         comptime = time.strftime( "%I:%M:%S%p %Z" )
>
>         logcomptime = open( "log.dat", "aa" )
>         logcomptime.write( " [Time Completed:  %(comptime)s]" % vars()
>         )
>         logcomptime.close()
>
>         print "Completed at %(comptime)s." % vars()
>         print "This window will close in 60 seconds."
>
>         time.sleep(60)
>         sys.exit()
>
>     if begin.lower in "n no".split():
>         print "FAILED"
>         print "This window will close in 60 seconds."
>
>         time.sleep( 60 )
>         sys.exit()



It might be good to split off sleep() into two separate functions, one to
handle the 'yes' case, and another to handle the 'no' case.  Let's see
what this might look like:


###
def sleep(a):
    currtime = time.strftime( "%I:%M:%S%p %Z" )
    print "Current time:  %(currtime)s" % vars()

    begin = raw_input( "Begin tracking?  [Y/N]:  " )

    if begin.lower() in "y yes".split():
        sleepYes(a)
    if begin.lower in "n no".split():
        sleepNo(a)


def sleepYes(a):
    logcurrtime = open( "log.dat", "aa" )
    logcurrtime.write( " [Current Time:  %(currtime)s]" % vars() )
    logcurrtime.close()
    int (a)
    sleeptime = a * 60
    int (sleeptime)

    logsleeptime = open( "log.dat", "aa" )
    logsleeptime.write( " [Sleep Time:  %(sleeptime)s Mins.]" %
                       vars() )
    logsleeptime.close()

    time.sleep( sleeptime )
    print "Set Time Complete"

    comptime = time.strftime( "%I:%M:%S%p %Z" )

    logcomptime = open( "log.dat", "aa" )
    logcomptime.write( " [Time Completed:  %(comptime)s]" % vars())
    logcomptime.close()

    print "Completed at %(comptime)s." % vars()
    print "This window will close in 60 seconds."

    time.sleep(60)
    sys.exit()


def sleepNo(a):
    print "FAILED"
    print "This window will close in 60 seconds."

    time.sleep( 60 )
    sys.exit()
###



One advantage of breaking down a function into smaller pieces is that it
becomes easier to look for places where parallelism breaks down.  For
example, now that sleep() is smaller, we can more easily pick out a small
bug in the second case, where we check if 'begin' is 'no':


###  within sleep()'s definition:

    if begin.lower() in "y yes".split():
        sleepYes(a)
    if begin.lower in "n no".split():         ## <-- buggy
        sleepNo(a)

###


This particular technique of breaking things down into smaller pieces is
also particularly useful in Python because it helps reduce block
indentation.  Python programmers think more about how to simplify and
split off smaller functions and methods because we simply have no choice:
the code otherwise becomes far too indented to work with.  *grin*


Hope this helps!