15. Classes and Methods
Object-Oriented Programming 3
- Object-oriented features
- Methods vs. functions
- Printing ojects
- A more complicated example
- The __init__ method
- The __str__ method
- Operator overloading
Although we are using some of Python’s object-oriented features, the programs from the last two chapters are not really object-oriented because they don’t represent the relationships between programmer-defined types and the functions that operate on them. The next step is to transform those functions into methods that make the relationships explicit.
Object-oriented features
- Programs include class and method definitions.
- Most of the computation is expressed in terms of operations on objects.
- Objects often represent things in the real world, and methods often correspond to the ways things in the real world interact.
Recall in Time1.py, every function takes at least one Time object as an argument.
This observation is the motivation for methods; a method is a function that is associated with a particular class. We have seen methods for strings, lists, dictionaries and tuples. In this chapter, we will define methods for programmer-defined types.
class Time:
"""Represents the time of day."""
def print_time(time):
print(f'{time.hour:02}:{time.minute:02}:{time.second:02}')
start = Time()
start.hour = 9
start.minute = 45
start.second = 0
print_time(start)
To make print_time
a method, all we have to do is move the function definition inside the class definition. Notice the change in indentation.
class Time:
def print_time(self):
print(f'{self.hour:02}:{self.minute:02}:{self.second:02}')
start = Time()
start.hour = 9
start.minute = 45
start.second = 0
# Two ways to call:
Time.print_time(start)
start.print_time()
- The syntax for a function call,
print_time(start)
, suggests that the function is the active agent. It says something like, “Hey print_time! Here’s an object for you to print.” - In object-oriented programming, the objects are the active agents. A method invocation like
start.print_time()
says “Hey start! Please print yourself.”
def is_after(self, other):
return self.time_to_int() > other.time_to_int()
# To use this method, you have to invoke it on one object
# and pass the other as an argument:
end = start.increment(1337)
end.is_after(start)
One nice thing about this syntax is that it almost reads like English: “end is after start?”
def __init__(self, hour=0, minute=0, second=0):
self.hour = hour
self.minute = minute
self.second = second
time = Time()
time.print_time()
time = Time (9)
time.print_time()
time = Time(9, 45)
time.print_time()
def __str__(self):
return f'{self.hour:02}:{self.minute:02}:{self.second:02}'
When you print
an object, Python invokes the str
method:
time = Time(9, 45)
print(time)
def __add__(self, other):
seconds = self.time_to_int() + other.time_to_int()
return int_to_time(seconds)
start = Time(9, 45)
duration = Time(1, 35)
print(start + duration)
When you apply the +
operator to Time objects, Python invokes __add__
. When you print the result, Python invokes __str__
. So there is a lot happening behind the scenes!
Changing the behavior of an operator so that it works with programmer-defined types is called operator overloading. For every operator in Python there is a corresponding special method, like __add__
. For more details, see http://docs.python.org/3/reference/datamodel.html#specialnames.
Exercise 04
Write an __add__
method for the Point
class.
Exercise 05 (group work)
Write a definition for a class of anything you want. You have to use the following methods:
-
__init__
method that initializes some attributes. One of the attributes has to be an empty list. -
__str__
method that returns a string that reasonably represent the thing. -
A special method that overloads the one type of operators.
-
Some other methods that reasonably represent the thing's actions, inclduing one method that takes an object of any type and adds it to the attribute of type list.
Test your code by creating two objects and using all the methods.