What are some other way to rewrite this if block?

Discussion in 'Python' started by Santosh Kumar, Mar 18, 2013.

  1. This simple script is about a public transport, here is the code:

    def report_status(should_be_on, came_on):
    if should_be_on < 0.0 or should_be_on > 24.0 or came_on < 0.0 or
    came_on > 24.0:
    return 'time not in range'
    elif should_be_on == came_on:
    return 'on time'
    elif should_be_on > came_on:
    return 'early'
    elif should_be_on < came_on:
    return 'delayed'
    return 'something might be wrong'

    print(report_status(123, 12.0))

    I am looking forward of make the line starting with `if` short.

    Any tips are welcome.
    Santosh Kumar, Mar 18, 2013
    1. Advertisements

  2. A double tip:

    if (not (0.0 <= should_be_on <= 24.0) or
    not (0.0 <= came_on <= 24.0)):

    You might want to raise an exception from the range-check branch
    instead of returning a value. And raise an exception from the
    else-branch, because that branch should never be reached.
    Jussi Piitulainen, Mar 18, 2013
    1. Advertisements

  3. If you have a lot of conditions to check, you can't really get around it.
    Yves S. Garret, Mar 18, 2013
  4. I'd still prefer to split the line, especially considering the fact
    that the request was to make the line shorter:

    if not (0.0 <= should_be_on <= 24.0 and
    0.0 <= came_on <= 24.0):
    Jussi Piitulainen, Mar 18, 2013

  5. Untested, but something like this should work. It adjusts for the times
    which fall either side of midnight, it optionally allows for some "slop"
    in deciding whether an arrival was on time or not (defaults to 0).

    def report(scheduled, actual, slop=0.0):
    """Report whether actual time of arrival is on time, late, early
    or cancelled.

    Pass actual=None for cancelled services, otherwise both scheduled and
    actual must be given as float hours between 0 and 24. E.g. to indicate
    a time of 06:30, pass 6.5.

    Optional argument slop is a non-negative time in hours which services
    are allowed to be late or early and still count as "on time". E.g. if
    a service is allowed to arrive with two minutes either side of the
    scheduled time and still count as on time, pass slop=2.0/60. The slop
    defaults to 0.0.

    if not 0 <= scheduled < 24:
    raise ValueError('scheduled time out of range')
    if not 0 <= slop < 24:
    raise ValueError('slop out of range')
    if actual is None:
    return "service cancelled"
    if not 0 <= actual < 24:
    raise ValueError('actual arrival time out of range')
    diff = actual - scheduled
    # Adjust for discontinuity around midnight. We assume that arrivals
    # are never more than 12 hours away from their scheduled times.
    if diff < -12:
    # For example, scheduled=23:55, actual=00:05 gives diff of -23:50
    diff += 24
    elif diff > 12:
    diff -= 24
    if diff < -slop:
    return "early"
    elif diff > slop:
    return "late"
    return "on time"

    One disadvantage with the function as written is that you have to give
    times as floats between 0 and 24, instead of a more natural HH:MM syntax.
    For example, 11:07am would have to be given as 11.116666666666667.

    Another weakness is that any slop allowance is symmetrical (e.g. you
    can't allow trains to arrive up to one minute early or five minutes late
    to be counted as "on time", the two figures have to be equal).

    A third weakness is that you can't allow for arrivals more than 12 hours
    early or late.

    Steven D'Aprano, Mar 18, 2013
  6. Oh, but that'll NEVER happen.

    Oh wait, I've been on a service that was 12 hours late.

    Is there any chance that you could do your times of arrival and
    expectation in, say, integer seconds since 1970?

    Chris Angelico, Mar 18, 2013
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.