[<< wikibooks] Think Python/Classes and functions
== Time ==
As another example of a user-defined type, we'll define a class called
Time that records the time of day. The class definition looks
like this:

We can create a new Time object and assign
attributes for hours, minutes, and seconds:

The state diagram for the Time object looks like this:


=== Exercise 1 ===
Write a function called print_time that takes a 
Time object and prints it in the form hour:minute:second.
Hint: the format sequence %.2d prints an integer using
at least two digits, including a leading zero if necessary.


=== Exercise 2 ===
Write a boolean function called is_after that
takes two Time objects, t1 and t2, and
returns True if t1 follows t2
chronologically and False otherwise. 
Challenge: don't use an if statement.


== Pure functions ==
In the next few sections, we’ll write two functions that add time
values. They demonstrate two kinds of functions: pure functions and
modifiers. They also demonstrate a development plan I’ll call prototype and patch, which is a way of tackling a complex problem
by starting with a simple prototype and incrementally dealing with the
complications.
Here is a simple prototype of add_time:

def add_time(t1, t2):
  sum = Time()
  sum.hour = t1.hour + t2.hour
  sum.minute = t1.minute + t2.minute
  sum.second = t1.second + t2.second
  return sum

The function creates a new Time object, initializes its
attributes, and returns a reference to the new object. This is called
a pure function because it does not modify any of the objects
passed to it as arguments and it has no effect,
like displaying a value or getting user input, 
other than returning a value.
To test this function, I’ll create two Time objects: start
contains the start time of a movie, like Monty Python and the
Holy Grail, and duration contains the run time of the movie,
which is one hour 35 minutes.
add_time figures out when the movie will be done.

>>> start = Time()
>>> start.hour = 9
>>> start.minute = 45
>>> start.second = 0

>>> duration = Time()
>>> duration.hour = 1
>>> duration.minute = 35
>>> duration.second = 0

>>> done = add_time(start, duration)
>>> print_time(done)
10:80:00

The result, 10:80:00 might not be what you were hoping
for. The problem is that this function does not deal with cases where the
number of seconds or minutes adds up to more than sixty. When that
happens, we have to “carry” the extra seconds into the minute column
or the extra minutes into the hour column.
Here’s an improved version:

def add_time(t1, t2):
  sum = Time()
  sum.hour = t1.hour + t2.hour
  sum.minute = t1.minute + t2.minute
  sum.second = t1.second + t2.second

  if sum.second >= 60:
    sum.second -= 60
    sum.minute += 1

  if sum.minute >= 60:
    sum.minute -= 60
    sum.hour += 1

  return sum

Although this function is correct, it is starting to get big.
We will see a shorter alternative later.


== Modifiers ==
Sometimes it is useful for a function to modify the objects it gets as
parameters. In that case, the changes are visible to the caller.
Functions that work this way are called modifiers.
increment, which adds a given number of seconds to a Time
object, can be written naturally as a
modifier. Here is a rough draft:

def increment(time, seconds):
  time.second += seconds

  if time.second >= 60:
    time.second -= 60
    time.minute += 1

  if time.minute >= 60:
    time.minute -= 60
    time.hour += 1

The first line performs the basic operation; the remainder deals
with the special cases we saw before.
Is this function correct? What happens if the parameter seconds
is much greater than sixty? 
In that case, it is not enough to carry
once; we have to keep doing it until time.second is less than sixty.
One solution is to replace the if statements with while
statements. That would make the function correct, but not
very efficient.

Anything that can be done with modifiers can also be done with pure
functions. In fact, some programming languages only allow pure
functions. There is some evidence that programs that use pure
functions are faster to develop and less error-prone than programs
that use modifiers. But modifiers are convenient at times,
and functional programs tend to be less efficient.
In general, I recommend that you write pure functions whenever it is
reasonable and resort to modifiers only if there is a compelling
advantage. This approach might be called a functional
programming style.