CH10 - Starting Out With Python
CH10 - Starting Out With Python
CHAPTER
10 Oriented Programming
TOPICS
10.1 Procedural and Object-Oriented 10.3 Working with Instances
Programming 10.4 Techniques for Designing Classes
10.2 Classes
There are primarily two methods of programming in use today: procedural and object-
oriented. The earliest programming languages were procedural, meaning a program was
made of one or more procedures. You can think of a procedure simply as a function that
performs a specific task such as gathering input from the user, performing calculations,
reading or writing files, displaying output, and so on. The programs that you have written
so far have been procedural in nature.
Typically, procedures operate on data items that are separate from the procedures. In a
procedural program, the data items are commonly passed from one procedure to another.
As you might imagine, the focus of procedural programming is on the creation of pro-
cedures that operate on the program’s data. The separation of data and the code that
operates on the data can lead to problems, however, as the program becomes larger and
more complex.
For example, suppose you are part of a programming team that has written an extensive
customer database program. The program was initially designed so a customer’s name,
543
address, and phone number were referenced by three variables. Your job was to design
several functions that accept those three variables as arguments and perform operations
on them. The software has been operating successfully for some time, but your team has
been asked to update it by adding several new features. During the revision process, the
senior programmer informs you that the customer’s name, address, and phone number
will no longer be stored in variables. Instead, they will be stored in a list. This means
you will have to modify all of the functions that you have designed so they accept and
work with a list instead of the three variables. Making these extensive modifications
not only is a great deal of work, but also opens the opportunity for errors to appear in
your code.
Whereas procedural programming is centered on creating procedures (functions), object-
oriented programming (OOP) is centered on creating objects. An object is a software
entity that contains both data and procedures. The data contained in an object is known as
the object’s data attributes. An object’s data attributes are simply variables that reference
data. The procedures that an object performs are known as methods. An object’s methods
are functions that perform operations on the object’s data attributes. The object is, con-
ceptually, a self-contained unit that consists of data attributes and methods that operate
on the data attributes. This is illustrated in Figure 10-1.
Object
Data attributes
OOP addresses the problem of code and data separation through encapsulation and data
hiding. Encapsulation refers to the combining of data and code into a single object. Data
hiding refers to an object’s ability to hide its data attributes from code that is outside the
object. Only the object’s methods may directly access and make changes to the object’s data
attributes.
An object typically hides its data, but allows outside code to access its methods. As shown
in Figure 10-2, the object’s methods provide programming statements outside the object
with indirect access to the object’s data attributes.
Figure 10-2 Code outside the object interacts with the object’s methods
Object
Data attributes
Code
outside the
object
When an object’s data attributes are hidden from outside code, and access to the data attri-
butes is restricted to the object’s methods, the data attributes are protected from accidental
corruption. In addition, the code outside the object does not need to know about the format
or internal structure of the object’s data. The code only needs to interact with the object’s
methods. When a programmer changes the structure of an object’s internal data attributes,
he or she also modifies the object’s methods so they may properly operate on the data. The
way in which outside code interacts with the methods, however, does not change.
Object Reusability
In addition to solving the problems of code and data separation, the use of OOP has also
been encouraged by the trend of object reusability. An object is not a stand-alone program,
but is used by programs that need its services. For example, Sharon is a programmer who
has developed a set of objects for rendering 3D images. She is a math whiz and knows a
lot about computer graphics, so her objects are coded to perform all of the necessary 3D
mathematical operations and handle the computer’s video hardware. Tom, who is writing a
program for an architectural firm, needs his application to display 3D images of buildings.
Because he is working under a tight deadline and does not possess a great deal of knowl-
edge about computer graphics, he can use Sharon’s objects to perform the 3D rendering
(for a small fee, of course!).
As you can see, the data attributes are merely values that define the state in which the
alarm clock is currently. You, the user of the alarm clock object, cannot directly manipu-
late these data attributes because they are private. To change a data attribute’s value, you
must use one of the object’s methods. The following are some of the alarm clock object’s
methods:
• set_time
• set_alarm_time
• set_alarm_on
• set_alarm_off
Each method manipulates one or more of the data attributes. For example, the set_time
method allows you to set the alarm clock’s time. You activate the method by pressing a
button on top of the clock. By using another button, you can activate the set_alarm_time
method.
In addition, another button allows you to execute the set_alarm_on and set_alarm_off
methods. Notice all of these methods can be activated by you, who are outside the alarm
clock. Methods that can be accessed by entities outside the object are known as public
methods.
The alarm clock also has private methods, which are part of the object’s private, internal
workings. External entities (such as you, the user of the alarm clock) do not have direct
access to the alarm clock’s private methods. The object is designed to execute these methods
automatically and hide the details from you. The following are the alarm clock object’s
private methods:
• increment_current_second
• increment_current_minute
• increment_current_hour
• sound_alarm
Every second the increment_current_second method executes. This changes the value
of the current_second data attribute. If the current_second data attribute is set to
59 when this method executes, the method is programmed to reset current_second
to 0, and then cause the increment_current_minute method to execute. This method
adds 1 to the current_minute data attribute, unless it is set to 59. In that case, it resets
urrent_minute to 0 and causes the increment_current_hour method to execute. The
c
increment_current_minute method compares the new time to the alarm_time. If the
two times match and the alarm is turned on, the sound_alarm method is executed.
Checkpoint
10.1 What is an object?
10.2 What is encapsulation?
10.3 Why is an object’s internal data usually hidden from outside code?
10.4 What are public methods? What are private methods?
10.2 Classes
CONCEPT: A class is code that specifies the data attributes and methods for a
particular type of object.
Now, let’s discuss how objects are created in software. Before an object can be created, it
must be designed by a programmer. The programmer determines the data attributes and
VideoNote
Classes and methods that are necessary, then creates a class. A class is code that specifies the data
Objects
attributes and methods of a particular type of object. Think of a class as a “blueprint”
from which objects may be created. It serves a similar purpose as the blueprint for a house.
The blueprint itself is not a house, but is a detailed description of a house. When we use
the blueprint to build an actual house, we could say we are building an instance of the
house described by the blueprint. If we so desire, we can build several identical houses
from the same blueprint. Each house is a separate instance of the house described by the
blueprint. This idea is illustrated in Figure 10-3.
Another way of thinking about the difference between a class and an object is to think of
the difference between a cookie cutter and a cookie. While a cookie cutter itself is not a
cookie, it describes a cookie. The cookie cutter can be used to make one cookie, or several
cookies. Think of a class as a cookie cutter, and the objects created from the class as
cookies.
So, a class is a description of an object’s characteristics. When the program is running, it
can use the class to create, in memory, as many objects of a specific type as needed. Each
object that is created from a class is called an instance of the class.
For example, Jessica is an entomologist (someone who studies insects), and she also enjoys
writing computer programs. She designs a program to catalog different types of insects. As
part of the program, she creates a class named Insect, which specifies characteristics that
are common to all types of insects. The Insect class is a specification from which objects
may be created. Next, she writes programming statements that create an object named
housefly, which is an instance of the Insect class. The housefly object is an entity that
occupies computer memory and stores data about a housefly. It has the data attributes and
methods specified by the Insect class. Then she writes programming statements that create
an object named mosquito. The mosquito object is also an instance of the Insect class.
It has its own area in memory and stores data about a mosquito. Although the housefly
and mosquito objects are separate entities in the computer’s memory, they were both cre-
ated from the Insect class. This means that each of the objects has the data attributes and
methods described by the Insect class. This is illustrated in Figure 10-4.
Figure 10-4 The housefly and mosquito objects are instances of the Insect class
Class Definitions
To create a class, you write a class definition. A class definition is a set of statements that
define a class’s methods and data attributes. Let’s look at a simple example. Suppose we are
writing a program to simulate the tossing of a coin. In the program, we need to repeatedly
toss the coin and each time determine whether it landed heads up or tails up. Taking an
object-oriented approach, we will write a class named Coin that can perform the behaviors
of the coin.
Program 10-1 shows the class definition, which we will explain shortly. Note this is not a
complete program. We will add to it as we go along.
1 import random
2
3 # The Coin class simulates a coin that can
4 # be flipped.
5
6 class Coin:
7
8 # The _ _init_ _ method initializes the
In line 1, we import the random module. This is necessary because we use the randint
function to generate a random number. Line 6 is the beginning of the class definition. It
begins with the keyword class, followed by the class name, which is Coin, followed by
a colon.
The same rules that apply to variable names also apply to class names. However, notice
that we started the class name, Coin, with an uppercase letter. This is not a requirement,
but it is a widely used convention among programmers. This helps to easily distinguish class
names from variable names when reading code.
The Coin class has three methods:
• The _ _init_ _ method appears in lines 11 through 12.
• The toss method appears in lines 19 through 23.
• The get_sideup method appears in lines 28 through 29.
Except for the fact that they appear inside a class, notice these method definitions look like
any other function definition in Python. They start with a header line, which is followed by
an indented block of statements.
Take a closer look at the header for each of the method definitions (lines 11, 19, and 28)
and notice each method has a parameter variable named self:
Line 11: def _ _init_ _(self):
Line 19: def toss(self):
Line 28: def get_sideup(self):
The self parameter1 is required in every method of a class. Recall from our earlier discus-
sion on object-oriented programming that a method operates on a specific object’s data
attributes. When a method executes, it must have a way of knowing which object’s data
attributes it is supposed to operate on. That’s where the self parameter comes in. When
a method is called, Python makes the self parameter reference the specific object that the
method is supposed to operate on.
Let’s look at each of the methods. The first method, which is named _ _init_ _, is defined
in lines 11 through 12:
def _ _init_ _(self):
self.sideup = 'Heads'
Most Python classes have a special method named _ _init_ _, which is automatically
executed when an instance of the class is created in memory. The _ _init_ _ method is
commonly known as an initializer method because it initializes the object’s data attributes.
(The name of the method starts with two underscore characters, followed by the word
init, followed by two more underscore characters.)
Immediately after an object is created in memory, the _ _init_ _ method executes, and
the self parameter is automatically assigned the object that was just created. Inside the
method, the statement in line 12 executes:
self.sideup = 'Heads'
This statement assigns the string 'Heads' to the sideup data attribute belonging to
the object that was just created. As a result of this _ _init_ _ method, each object we
create from the Coin class will initially have a sideup attribute that is set to 'Heads'.
NOTE: The _ _init_ _ method is usually the first method inside a class definition.
This method also has the required self parameter variable. When the toss method is
called, self will automatically reference the object on which the method is to operate.
The toss method simulates the tossing of the coin. When the method is called, the if
statement in line 20 calls the random.randint function to get a random integer in the
range of 0 through 1. If the number is 0, then the statement in line 21 assigns 'Heads'
to self.sideup. Otherwise, the statement in line 23 assigns 'Tails' to self.sideup.
1
The parameter must be present in a method. You are not required to name it self, but this is
strongly recommended to conform with standard practice.
Once again, the method has the required self parameter variable. This method simply
returns the value of self.sideup. We call this method any time we want to know which
side of the coin is facing up.
To demonstrate the Coin class, we need to write a complete program that uses it to create
an object. Program 10-2 shows an example. The Coin class definition appears in lines 6
through 29. The program has a main function, which appears in lines 32 through 44.
1 import random
2
3 # The Coin class simulates a coin that can
4 # be flipped.
5
6 class Coin:
7
8 # The _ _init_ _ method initializes the
9 # sideup data attribute with 'Heads'.
10
11 def _ _init_ _(self):
12 self.sideup = 'Heads'
13
14 # The toss method generates a random number
15 # in the range of 0 through 1. If the number
16 # is 0, then sideup is set to 'Heads'.
17 # Otherwise, sideup is set to 'Tails'.
18
19 def toss(self):
20 if random.randint(0, 1) == 0:
21 self.sideup = 'Heads'
22 else:
23 self.sideup = 'Tails'
24
25 # The get_sideup method returns the value
26 # referenced by sideup.
27
28 def get_sideup(self):
29 return self.sideup
30
31 # The main function.
32 def main():
33 # Create an object from the Coin class.
(program continues)
34 my_coin = Coin()
35
36 # Display the side of the coin that is facing up.
37 print('This side is up:', my_coin.get_sideup())
38
39 # Toss the coin.
40 print('I am tossing the coin ...')
41 my_coin.toss()
42
43 # Display the side of the coin that is facing up.
44 print('This side is up:', my_coin.get_sideup())
45
46 # Call the main function.
47 47 if _ _name_ _ == '_ _main_ _':
48 main()
Program Output
This side is up: Heads
I am tossing the coin ...
This side is up: Tails
Program Output
This side is up: Heads
I am tossing the coin ...
This side is up: Heads
Program Output
This side is up: Heads
I am tossing the coin ...
This side is up: Tails
The expression Coin() that appears on the right side of the = operator causes two things
to happen:
1. An object is created in memory from the Coin class.
2. The Coin class’s _ _init_ _ method is executed, and the self parameter is automati-
cally set to the object that was just created. As a result, that object’s sideup attribute
is assigned the string 'Heads'.
Figure 10-5 illustrates these steps.
A Coin object
After these steps take place,
a Coin object will exist with its sideup 'Heads'
sideup attribute set to 'Heads'.
After this, the = operator assigns the Coin object that was just created to the my_coin
variable. Figure 10-6 shows that after the statement in line 12 executes, the my_coin
variable will reference a Coin object, and that object’s sideup attribute will be assigned
the string 'Heads'.
A Coin object
This statement prints a message indicating the side of the coin that is facing up. Notice
the following expression appears in the statement:
my_coin.get_sideup()
This expression uses the object referenced by my_coin to call the get_sideup method.
When the method executes, the self parameter will reference the my_coin object. As a
result, the method returns the string 'Heads'.
Notice we did not have to pass an argument to the sideup method, despite the fact that
it has the self parameter variable. When a method is called, Python automatically passes
a reference to the calling object into the method’s first parameter. As a result, the self
parameter will automatically reference the object on which the method is to operate.
The statement in line 41 uses the object referenced by my_coin to call the toss method.
When the method executes, the self parameter will reference the my_coin object. The
method will randomly generate a number, then use that number to change the value of the
object’s sideup attribute.
Line 44 executes next. This statement calls my_coin.get_sideup() to display the side of
the coin that is facing up.
Hiding Attributes
Earlier in this chapter, we mentioned that an object’s data attributes should be private,
so that only the object’s methods can directly access them. This protects the object’s data
attributes from accidental corruption. However, in the Coin class that was shown in the
previous example, the sideup attribute is not private. It can be directly accessed by state-
ments that are not in a Coin class method. Program 10-3 shows an example. Note lines 1
through 30 are not shown to conserve space. Those lines contain the Coin class, and they
are the same as lines 1 through 30 in Program 10-2.
Lines 1 through 30 are omitted. These lines are the same as lines 1 through 30 in Program 10-2.
31 # The main function.
32 def main():
33 # Create an object from the Coin class.
34 my_coin = Coin()
35
36 # Display the side of the coin that is facing up.
37 print('This side is up:', my_coin.get_sideup())
38
39 # Toss the coin.
40 print('I am tossing the coin ...')
41 my_coin.toss()
42
43 # But now I'm going to cheat! I'm going to
44 # directly change the value of the object's
45 # sideup attribute to 'Heads'.
46 my_coin.sideup = 'Heads'
47
48 # Display the side of the coin that is facing up.
49 print('This side is up:', my_coin.get_sideup())
50
51 # Call the main function.
52 if _ _name_ _ == '_ _main_ _':
53 main()
Program Output
This side is up: Heads
I am tossing the coin ...
This side is up: Heads
Program Output
This side is up: Heads
I am tossing the coin ...
This side is up: Heads
Program Output
This side is up: Heads
I am tossing the coin ...
This side is up: Heads
Line 34 creates a Coin object in memory and assigns it to the my_coin variable. The state-
ment in line 37 displays the side of the coin that is facing up, then line 41 calls the object’s
toss method. Then, the statement in line 46 directly assigns the string 'Heads' to the obj
ect’s sideup attribute:
my_coin.sideup = 'Heads'
Regardless of the outcome of the toss method, this statement will change the my_coin
object’s sideup attribute to 'Heads'. As you can see from the three sample runs of the
program, the coin always lands heads up!
If we truly want to simulate a coin that is being tossed, then we don’t want code outside the
class to be able to change the result of the toss method. To prevent this from happening,
we need to make the sideup attribute private. In Python, you can hide an attribute by start-
ing its name with two underscore characters. If we change the name of the sideup attribute
to _ _sideup, then code outside the Coin class will not be able to access it. Program 10-4
shows a new version of the Coin class, with this change made.
1 import random
2
3 # The Coin class simulates a coin that can
4 # be flipped.
5
6 class Coin:
7
8 # The _ _init_ _ method initializes the
9 # _ _sideup data attribute with ‘Heads’.
10
11 def _ _init_ _(self):
12 self._ _sideup = 'Heads'
13
(program continues)
Program Output
This side is up: Heads
I am going to toss the coin ten times:
Tails
Heads
Heads
Tails
Tails
Tails
Tails
Tails
Heads
Heads
1 import random
2
3 # The Coin class simulates a coin that can
4 # be flipped.
5
6 class Coin:
7
8 # The _ _init_ _ method initializes the
9 # _ _sideup data attribute with 'Heads'.
10
11 def _ _init_ _(self):
12 self._ _sideup = 'Heads'
13
14 # The toss method generates a random number
15 # in the range of 0 through 1. If the number
16 # is 0, then sideup is set to 'Heads'.
17 # Otherwise, sideup is set to 'Tails'.
18
19 def toss(self):
20 if random.randint(0, 1) == 0:
21 self._ _sideup = 'Heads'
22 else:
23 self._ _sideup = 'Tails'
24
25 # The get_sideup method returns the value
(program continues)
26 # referenced by sideup.
27
28 def get_sideup(self):
29 return self._ _sideup
Program Output
This side is up: Heads
I am going to toss the coin ten times:
Tails
Tails
Heads
Tails
Heads
Heads
Tails
Heads
Tails
Tails
Line 4 imports the coin module. Notice in line 8, we had to qualify the name of the Coin
class by prefixing it with the name of the module, followed by a dot:
my_coin = coin.Coin()
Notice the _ _init_ _ method has two parameter variables: self and bal. The bal param-
eter will accept the account’s starting balance as an argument. In line 10, the bal parameter
amount is assigned to the object’s _ _balance attribute.
The deposit method is in lines 15 through 16. This method has two parameter variables:
self and amount. When the method is called, the amount that is to be deposited into the
account is passed into the amount parameter. The value of the parameter is then added to
the _ _balance attribute in line 16.
The withdraw method is in lines 21 through 25. This method has two parameter variables:
self and amount. When the method is called, the amount that is to be withdrawn from
the account is passed into the amount parameter. The if statement that begins in line 22
determines whether there is enough in the account balance to make the withdrawal. If so,
amount is subtracted from _ _balance in line 23. Otherwise, line 25 displays the message
'Error: Insufficient funds'.
The get_balance method is in lines 30 through 31. This method returns the value of the
_ _balance attribute.
Line 7 gets the starting account balance from the user and assigns it to the start_bal vari-
able. Line 10 creates an instance of the BankAccount class and assigns it to the savings
variable. Take a closer look at the statement:
savings = bankaccount.BankAccount(start_bal)
Notice the start_bal variable is listed inside the parentheses. This causes the start_bal
variable to be passed as an argument to the _ _init_ _ method. In the _ _init_ _ method, it
will be passed into the bal parameter.
Line 13 gets the amount of the user’s pay and assigns it to the pay variable. In line 15,
the savings.deposit method is called, passing the pay variable as an argument. In the
deposit method, it will be passed into the amount parameter.
The statement in line 18 displays the account balance. Notice that we are using an f-string
to call the savings.get_balance method. The value that is returned from the method is
formatted to appear as a dollar amount.
Line 21 gets the amount that the user wants to withdraw and assigns it to the cash vari-
able. In line 23 the savings.withdraw method is called, passing the cash variable as
an argument. In the withdraw method, it will be passed into the amount parameter. The
statement in line 26 displays the ending account balance.
_ _balance attribute represents the object’s state at that moment. The following might be
an example of code that displays a BankAccount object’s state:
account = bankaccount.BankAccount(1500.0)
print(f'The balance is ${savings.get_balance():,.2f}'))
The first statement creates a BankAccount object, passing the value 1500.0 to the
_ _init_ _ method. After this statement executes, the account variable will reference the
BankAccount object. The second line displays a formatted string showing the value of
the object’s _ _balance attribute. The output of this statement will look like this:
The balance is $1,500.00
You do not directly call the _ _str_ _ method. Instead, it is automatically called when you
pass an object as an argument to the print function. Program 10-10 shows an example.
The name of the object, savings, is passed to the print function in lines 19 and 27. This
causes the BankAccount class’s _ _str_ _ method to be called. The string that is returned
from the _ _str_ _ method is then displayed.
The _ _str_ _ method is also called automatically when an object is passed as an argument
to the built-in str function. Here is an example:
account = bankaccount2.BankAccount(1500.0)
message = str(account)
print(message)
In the second statement, the account object is passed as an argument to the str function.
This causes the BankAccount class’s _ _str_ _ method to be called. The string that is returned
is assigned to the message variable then displayed by the print function in the third line.
Checkpoint
10.5 You hear someone make the following comment: “A blueprint is a design for
a house. A carpenter can use the blueprint to build the house. If the carpenter
wishes, he or she can build several identical houses from the same blueprint.”
Think of this as a metaphor for classes and objects. Does the blueprint represent
a class, or does it represent an object?
10.6 In this chapter, we use the metaphor of a cookie cutter and cookies that are
made from the cookie cutter to describe classes and objects. In this metaphor, are
objects the cookie cutter, or the cookies?
10.7 What is the purpose of the _ _init_ _ method? When does it execute?
10.8 What is the purpose of the self parameter in a method?
10.9 In a Python class, how do you hide an attribute from code outside the class?
10.10 What is the purpose of the _ _str_ _ method?
10.11 How do you call the _ _str_ _ method?
CONCEPT: Each instance of a class has its own set of data attributes.
When a method uses the self parameter to create an attribute, the attribute belongs to the
specific object that self references. We call these attributes instance attributes because they
belong to a specific instance of the class.
It is possible to create many instances of the same class in a program. Each instance will
then have its own set of attributes. For example, look at Program 10-11. This program
creates three instances of the Coin class. Each instance has its own _ _sideup attribute.
Program Output
I have three coins with these sides up:
Heads
Heads
Heads
In lines 8 through 10, the following statements create three objects, each an instance of the
Coin class:
coin1 = coin.Coin()
coin2 = coin.Coin()
coin3 = coin.Coin()
Figure 10-7 illustrates how the coin1, coin2, and coin3 variables reference the three
objects after these statements execute. Notice each object has its own _ _sideup attribute.
Lines 14 through 16 display the values returned from each object’s get_sideup method.
Figure 10-7 The coin1, coin2, and coin3 variables reference three Coin objects
A Coin object
A Coin object
A Coin object
Then, the statements in lines 22 through 24 call each object’s toss method:
coin1.toss()
coin2.toss()
coin3.toss()
Figure 10-8 shows how these statements changed each object’s _ _sideup attribute in the
program’s sample run.
A Coin object
A Coin object
In the Spotlight:
Creating the CellPhone Class
Wireless Solutions, Inc. is a business that sells cell phones and wireless service. You are a
programmer in the company’s IT department, and your team is designing a program to
manage all of the cell phones that are in inventory. You have been asked to design a class
that represents a cell phone. The data that should be kept as attributes in the class are as
follows:
• The name of the phone’s manufacturer will be assigned to the _ _manufact attribute.
• The phone’s model number will be assigned to the _ _model attribute.
• The phone’s retail price will be assigned to the _ _retail_price attribute.
The class will also have the following methods:
• An _ _init_ _ method that accepts arguments for the manufacturer, model number,
and retail price.
• A set_manufact method that accepts an argument for the manufacturer. This method
will allow us to change the value of the _ _manufact attribute after the object has
been created, if necessary.
• A set_model method that accepts an argument for the model. This method will allow
us to change the value of the _ _model attribute after the object has been created, if
necessary.
• A set_retail_price method that accepts an argument for the retail price. This
method will allow us to change the value of the _ _retail_price attribute after the
object has been created, if necessary.
• A get_manufact method that returns the phone’s manufacturer.
• A get_model method that returns the phone’s model number.
• A get_retail_price method that returns the phone’s retail price.
Program 10-12 shows the class definition. The class is stored in a module named cellphone.
17
18 # The set_model method accepts an argument for
19 # the phone's model number.
20
21 def set_model(self, model):
22 self._ _model = model
23
24 # The set_retail_price method accepts an argument
25 # for the phone's retail price.
26
27 def set_retail_price(self, price):
28 self._ _retail_price = price
29
30 # The get_manufact method returns the
31 # phone's manufacturer.
32
33 def get_manufact(self):
34 return self._ _manufact
35
36 # The get_model method returns the
37 # phone's model number.
38
39 def get_model(self):
40 return self._ _model
41
42 # The get_retail_price method returns the
43 # phone's retail price.
44
45 def get_retail_price(self):
46 return self._ _retail_price
The CellPhone class will be imported into several programs that your team is develop-
ing. To test the class, you write the code in Program 10-13. This is a simple program that
prompts the user for the phone’s manufacturer, model number, and retail price. An instance
of the CellPhone class is created, and the data is assigned to its attributes.
A method that stores a value in a data attribute or changes the value of a data attribute
in some other way is known as a mutator method. Mutator methods can control the way
that a class’s data attributes are modified. When code outside the class needs to change
the value of an object’s data attribute, it typically calls a mutator and passes the new
value as an argument. If necessary, the mutator can validate the value before it assigns it to
the data attribute. In Program 10-12, the set_manufact, set_model, and set_retail_
price methods are mutator methods.
NOTE: Mutator methods are sometimes called “setters,” and accessor methods are
sometimes called “getters.”
In the Spotlight:
Storing Objects in a List
The CellPhone class you created in the previous In the Spotlight section will be used in a
variety of programs. Many of these programs will store CellPhone objects in lists. To test
the ability to store CellPhone objects in a list, you write the code in Program 10-14. This
program gets the data for five phones from the user, creates five CellPhone objects hold-
ing that data, and stores those objects in a list. It then iterates over the list displaying the
attributes of each object.
38
39 # Return the list.
40 return phone_list
41
42 # The display_list function accepts a list containing
43 # CellPhone objects as an argument and displays the
44 # data stored in each object.
45
46 def display_list(phone_list):
47 for item in phone_list:
48 print(item.get_manufact())
49 print(item.get_model())
50 print(item.get_retail_price())
51 print()
52
53 # Call the main function.
54 if _ _name_ _ == '_ _main_ _':
55 main()
Phone number 1:
Enter the manufacturer: Acme Electronics Enter
Enter the model number: M1000 Enter
Enter the retail price: 199.99 Enter
Phone number 2:
Enter the manufacturer: Atlantic Communications Enter
Enter the model number: S2 Enter
Enter the retail price: 149.99 Enter
Phone number 3:
Enter the manufacturer: Wavelength Electronics Enter
Enter the model number: N477 Enter
Enter the retail price: 249.99 Enter
Phone number 4:
Enter the manufacturer: Edison Wireless Enter
Enter the model number: SLX88 Enter
Enter the retail price: 169.99 Enter
Phone number 5:
Enter the manufacturer: Sonic Systems Enter
Enter the model number: X99 Enter
Enter the retail price: 299.99 Enter
Wavelength Electronics
N477
249.99
Edison Wireless
SLX88
169.99
Sonic Systems
X99
299.99
The make_list function appears in lines 18 through 40. In line 20, an empty list named
phone_list is created. The for loop, which begins in line 24, iterates five times. Each time
the loop iterates, it gets the data for a cell phone from the user (lines 27 through 29), it
creates an instance of the CellPhone class that is initialized with the data (line 34), and it
appends the object to the phone_list list (line 37). Line 40 returns the list.
The display_list function in lines 46 through 51 accepts a list of CellPhone objects as
an argument. The for loop that begins in line 47 iterates over the objects in the list, and
displays the values of each object’s attributes.
The following code sample shows how we might create a Coin object, then pass it as an
argument to the show_coin_status function:
my_coin = coin.Coin()
show_coin_status(my_coin)
When you pass a object as an argument, the thing that is passed into the parameter variable
is a reference to the object. As a result, the function or method that receives the object as an
argument has access to the actual object. For example, look at the following flip method:
def flip(coin_obj):
coin_obj.toss()
This method accepts a Coin object as an argument, and it calls the object’s toss method.
Program 10-15 demonstrates the method.
Program Output
Heads
Tails
Program Output
Heads
Heads
Program Output
Heads
Tails
The statement in line 8 creates a Coin object, referenced by the variable my_coin.
Line 11 displays the value of the my_coin object’s _ _sideup attribute. Because the object’s
_ _init_ _ method set the _ _sideup attribute to 'Heads', we know that line 11 will dis-
play the string 'Heads'. Line 14 calls the flip function, passing the my_coin object as
an argument. Inside the flip function, the my_coin object’s toss method is called. Then,
line 18 displays the value of the my_coin object’s _ _sideup attribute again. This time,
we cannot predict whether 'Heads' or 'Tails' will be displayed because the my_coin
object’s toss method has been called.
In the Spotlight:
Pickling Your Own Objects
Recall from Chapter 9 that the pickle module provides functions for serializing objects.
Serializing an object means converting it to a stream of bytes that can be saved to a file for
later retrieval. The pickle module’s dump function serializes (pickles) an object and writes it
to a file, and the load function retrieves an object from a file and deserializes (unpickles) it.
In Chapter 9, you saw examples in which dictionary objects were pickled and unpickled.
You can also pickle and unpickle objects of your own classes. Program 10-16 shows an
example that pickles three CellPhone objects and saves them to a file. Program 10-17
retrieves those objects from the file and unpickles them.
34
35 # Call the main function.
36 if _ _name_ _ == '_ _main_ _':
37 main()
Program Output
Manufacturer: ACME Electronics
Model Number: M1000
Retail Price: $199.99
In the Spotlight:
Storing Objects in a Dictionary
Recall from Chapter 9 that dictionaries are objects that store elements as key-value pairs.
Each element in a dictionary has a key and a value. If you want to retrieve a specific value
from the dictionary, you do so by specifying its key. In Chapter 9, you saw examples that
stored values such as strings, integers, floating-point numbers, lists, and tuples in dictio-
naries. Dictionaries are also useful for storing objects that you create from your own classes.
Let’s look at an example. Suppose you want to create a program that keeps contact infor-
mation, such as names, phone numbers, and email addresses. You could start by writing a
class such as the Contact class, shown in Program 10-18. An instance of the Contact class
keeps the following data:
• A person’s name is stored in the _ _name attribute.
• A person’s phone number is stored in the _ _phone attribute.
• A person’s email address is stored in the _ _email attribute.
The class has the following methods:
• An _ _init_ _ method that accepts arguments for a person’s name, phone number,
and email address
• A set_name method that sets the _ _name attribute
Next, you could write a program that keeps Contact objects in a dictionary. Each time
the program creates a Contact object holding a specific person’s data, that object would
be stored as a value in the dictionary, using the person’s name as the key. Then, any time
you need to retrieve a specific person’s data, you would use that person’s name as a key to
retrieve the Contact object from the dictionary.
Program 10-19 shows an example. The program displays a menu that allows the user to
perform any of the following operations:
• Look up a contact in the dictionary
• Add a new contact to the dictionary
• Change an existing contact in the dictionary
• Delete a contact from the dictionary
• Quit the program
Additionally, the program automatically pickles the dictionary and saves it to a file when
the user quits the program. When the program starts, it automatically retrieves and unpick-
les the dictionary from the file. (Recall from Chapter 10 that pickling an object saves it to a
file, and unpickling an object retrieves it from a file.) If the file does not exist, the program
starts with an empty dictionary.
The program is divided into eight functions: main, load_contacts, get_menu_choice,
look_up, add, change, delete, and save_contacts. Rather than presenting the entire
program at once, let’s first examine the beginning part, which includes the import state-
ments, global constants, and the main function.
23
24 # Process menu selections until the user
25 # wants to quit the program.
26 while choice != QUIT:
27 # Get the user's menu choice.
28 choice = get_menu_choice()
29
30 # Process the choice.
31 if choice == LOOK_UP:
32 look_up(mycontacts)
33 elif choice == ADD:
34 add(mycontacts)
35 elif choice == CHANGE:
36 change(mycontacts)
37 elif choice == DELETE:
38 delete(mycontacts)
39
40 # Save the mycontacts dictionary to a file.
41 save_contacts(mycontacts)
42
Line 2 imports the contact module, which contains the Contact class. Line 3 imports the
pickle module. The global constants that are initialized in lines 6 through 10 are used to
test the user’s menu selection. The FILENAME constant that is initialized in line 13 holds the
name of the file that will contain the pickled copy of the dictionary, which is contacts.dat.
Inside the main function, line 19 calls the load_contacts function. Keep in mind that if
the program has been run before and names were added to the dictionary, those names
have been saved to the contacts.dat file. The load_contacts function opens the file,
gets the dictionary from it, and returns a reference to the dictionary. If the program has not
been run before, the contacts.dat file does not exist. In that case, the load_contacts
function creates an empty dictionary and returns a reference to it. So, after the statement in
line 19 executes, the mycontacts variable references a dictionary. If the program has been
run before, mycontacts references a dictionary containing Contact objects. If this is the
first time the program has run, mycontacts references an empty dictionary.
Line 22 initializes the choice variable with the value 0. This variable will hold the user’s
menu selection.
The while loop that begins in line 26 repeats until the user chooses to quit the program.
Inside the loop, line 28 calls the get_menu_choice function. The get_menu_choice func-
tion displays the following menu:
1. Look up a contact
2. Add a new contact
3. Change an existing contact
4. Delete a contact
5. Quit the program
The user’s selection is returned from the get_menu_choice function and is assigned to the
choice variable.
The if-elif statement in lines 31 through 38 processes the user’s menu choice. If the user
selects item 1, line 32 calls the look_up function. If the user selects item 2, line 34 calls the
add function. If the user selects item 3, line 36 calls the change function. If the user selects
item 4, line 38 calls the delete function.
When the user selects item 5 from the menu, the while loop stops repeating, and the
statement in line 41 executes. This statement calls the save_contacts function, passing
mycontacts as an argument. The save_contacts function saves the mycontacts dictio
nary to the contacts.dat file.
The load_contacts function is next.
43 def load_contacts():
44 try:
45 # Open the contacts.dat file.
46 input_file = open(FILENAME, 'rb')
47
48 # Unpickle the dictionary.
49 contact_dct = pickle.load(input_file)
50
51 # Close the phone_inventory.dat file.
52 input_file.close()
53 except IOError:
54 # Could not open the file, so create
55 # an empty dictionary.
56 contact_dct = {}
57
58 # Return the dictionary.
59 return contact_dct
60
Inside the try suite, line 46 attempts to open the contacts.dat file. If the file is successfully
opened, line 49 loads the dictionary object from it, unpickles it, and assigns it to the con-
tact_dct variable. Line 52 closes the file.
If the contacts.dat file does not exist (this will be the case the first time the program
runs), the statement in line 46 raises an IOError exception. That causes the program to
jump to the except clause in line 53. Then, the statement in line 56 creates an empty dic-
tionary and assigns it to the contact_dct variable.
The statement in line 59 returns the contact_dct variable.
The get_menu_choice function is next.
The statements in lines 64 through 72 display the menu on the screen. Line 75 prompts
the user to enter his or her choice. The input is converted to an int and assigned to the
choice variable. The while loop in lines 78 through 79 validates the user’s input and, if
necessary, prompts the user to reenter his or her choice. Once a valid choice is entered, it
is returned from the function in line 82.
The look_up function is next.
The purpose of the look_up function is to allow the user to look up a specified contact.
It accepts the mycontacts dictionary as an argument. Line 88 prompts the user to enter a
name, and line 91 passes that name as an argument to the dictionary’s get function. One of
the following actions will happen as a result of line 91:
• If the specified name is found as a key in the dictionary, the get method returns a
reference to the Contact object that is associated with that name. The Contact object
is then passed as an argument to the print function. The print function displays the
string that is returned from the Contact object’s _ _str_ _ method.
• If the specified name is not found as a key in the dictionary, the get method returns
the string 'That name is not found.', which is displayed by the print function.
The add function is next.
The purpose of the add function is to allow the user to add a new contact to the dictionary.
It accepts the mycontacts dictionary as an argument. Lines 97 through 99 prompt the user
to enter a name, a phone number, and an email address. Line 102 creates a new Contact
object, initialized with the data entered by the user.
The if statement in line 107 determines whether the name is already in the dictionary. If
not, line 108 adds the newly created Contact object to the dictionary, and line 109 prints
a message indicating that the new data is added. Otherwise, a message indicating that the
entry already exists is printed in line 111.
The change function is next.
The purpose of the change function is to allow the user to change an existing contact in
the dictionary. It accepts the mycontacts dictionary as an argument. Line 117 gets a name
from the user. The if statement in line 119 determines whether the name is in the dictio-
nary. If so, line 121 gets the new phone number, and line 124 gets the new email address.
Line 127 creates a new Contact object initialized with the existing name and the new
phone number and email address. Line 130 stores the new Contact object in the dictio-
nary, using the existing name as the key.
If the specified name is not in the dictionary, line 133 prints a message indicating so.
The delete function is next.
The purpose of the delete function is to allow the user to delete an existing contact from
the dictionary. It accepts the mycontacts dictionary as an argument. Line 139 gets a name
from the user. The if statement in line 142 determines whether the name is in the dictio-
nary. If so, line 143 deletes it, and line 144 prints a message indicating that the entry was
deleted. If the name is not in the dictionary, line 146 prints a message indicating so.
The save_contacts function is next.
The save_contacts function is called just before the program stops running. It accepts the
mycontacts dictionary as an argument. Line 152 opens the contacts.dat file for writing.
Line 155 pickles the mycontacts dictionary and saves it to the file. Line 158 closes the file.
The following program output shows two sessions with the program. The sample output
does not demonstrate everything the program can do, but it does demonstrate how contacts
are saved when the program ends and then loaded when the program runs again.
Menu
---------------------------
1. Look up a contact
2. Add a new contact
3. Change an existing contact
4. Delete a contact
5. Quit the program
Menu
---------------------------
1. Look up a contact
2. Add a new contact
3. Change an existing contact
4. Delete a contact
5. Quit the program
Menu
---------------------------
1. Look up a contact
2. Add a new contact
3. Change an existing contact
4. Delete a contact
5. Quit the program
Checkpoint
10.12 What is an instance attribute?
10.13 A program creates 10 instances of the Coin class. How many _ _sideup
attributes exist in memory?
10.14 What is an accessor method? What is a mutator method?
Following this layout, Figure 10-10 and 10-11 show UML diagrams for the Coin class and
the CellPhone class that you saw previously in this chapter. Notice we did not show the
self parameter in any of the methods, since it is understood that the self parameter is
required.
Coin
__sideup
__init__( )
toss( )
get_sideup( )
CellPhone
__manufact
__model
__retail_price
__init__(manufact, model, price)
set_manufact(manufact)
set_model(model)
set_retail_price(price)
get_manufact()
get_model()
get_retail_price()
Notice some of the nouns are repeated. The following list shows all of the nouns without
duplicating any of them:
address
BMW
car
cars
customer
estimated labor charges
estimated parts charges
foreign cars
Joe’s Automotive Shop
make
manager
Mercedes
model
name
Porsche
sales tax
service quote
shop
telephone number
total estimated charges
year
address
BMW
car
cars
customer Because car, cars, and foreign cars mean
estimated labor charges the same thing in this problem, we have
eliminated cars and foreign cars. Also,
estimated parts charges
because Joe’s Automotive Shop and shop
foreign cars mean the same thing, we have eliminated
Joe’s Automotive Shop Joe’s Automotive Shop.
make
manager
Mercedes
model
name
Porsche
sales tax
service quote
(continued)
shop
telephone number
total estimated charges
year
2. Some nouns might represent items that we do not need to be concerned with in order
to solve the problem.
A quick review of the problem description reminds us of what our application should do:
print a service quote. In this example, we can eliminate two unnecessary classes from the list:
• We can cross shop off the list because our application only needs to be concerned with
individual service quotes. It doesn’t need to work with or determine any company-wide
information. If the problem description asked us to keep a total of all the service quotes,
then it would make sense to have a class for the shop.
• We will not need a class for the manager because the problem statement does not
direct us to process any information about the manager. If there were multiple shop
managers, and the problem description had asked us to record which manager gener-
ated each service quote, then it would make sense to have a class for the manager.
The updated list of potential classes at this point is:
address
BMW
car
cars
customer
estimated labor charges
estimated parts charges
foreign cars
Joe’s Automotive Shop
make
Our problem description does not direct us to
manager process any information about the shop, or any
Mercedes information about the manager, so we have
model eliminated those from the list.
name
Porsche
sales tax
service quote
shop
telephone number
total estimated charges
year
address
BMW
car
cars
customer
estimated labor charges
estimated parts charges
foreign cars We have eliminated Mercedes, Porsche, and
Joe’s Automotive Shop BMW because they are all instances of a car
class. That means that these nouns identify
manager
objects, not classes.
make
Mercedes
model
name
Porsche
sales tax
service quote
shop
telephone number
total estimated charges
year
NOTE: Some object-oriented designers take note of whether a noun is plural or singular.
Sometimes a plural noun will indicate a class, and a singular noun will indicate an object.
4. Some of the nouns might represent simple values that can be assigned to a variable
and do not require a class.
Remember, a class contains data attributes and methods. Data attributes are related items
that are stored in an object of the class and define the object’s state. Methods are actions
or behaviors that can be performed by an object of the class. If a noun represents a type
of item that would not have any identifiable data attributes or methods, then it can prob-
ably be eliminated from the list. To help determine whether a noun represents an item that
would have data attributes and methods, ask the following questions about it:
• Would you use a group of related values to represent the item’s state?
• Are there any obvious actions to be performed by the item?
If the answers to both of these questions are no, then the noun probably represents a value
that can be stored in a simple variable. If we apply this test to each of the nouns that remain
in our list, we can conclude that the following are probably not classes: address, estimated
labor charges, estimated parts charges, make, model, name, sales tax, telephone number,
total estimated charges, and year. These are all simple string or numeric values that can be
stored in variables. Here is the updated list of potential classes:
Address
BMW
car
cars
customer
estimated labor charges We have eliminated address, estimated
estimated parts charges labor charges, estimated parts charges,
make, model, name, sales tax, telephone
foreign cars
number, total estimated charges, and
Joe’s Automotive Shop year as classes because they represent
make simple values that can be stored in
manager variables.
Mercedes
model
name
Porsche
sales tax
service quote
shop
telephone number
total estimated charges
year
As you can see from the list, we have eliminated everything except car, customer, and
service quote. This means that in our application, we will need classes to represent cars,
customers, and service quotes. Ultimately, we will write a Car class, a Customer class, and
a ServiceQuote class.
When you have identified the things that a class is responsible for knowing, then you have
identified the class’s data attributes. Likewise, when you have identified the actions that a
class is responsible for doing, you have identified its methods.
It is often helpful to ask the questions “In the context of this problem, what must the class
know? What must the class do?” The first place to look for the answers is in the descrip-
tion of the problem domain. Many of the things that a class must know and do will be
mentioned. Some class responsibilities, however, might not be directly mentioned in the
problem domain, so further consideration is often required. Let’s apply this methodology
to the classes we previously identified from our problem domain.
Customer
__name
__address
__phone
__init__(name, address,
phone)
set_name(name)
set_address(address)
set_phone(phone)
get_name()
get_address()
get_phone()
1 # Customer class
2 class Customer:
3 def _ _init_ _(self, name, address, phone):
4 self._ _name = name
5 self._ _address = address
6 self._ _phone = phone
7
8 def set_name(self, name):
9 self._ _name = name
10
11 def set_address(self, address):
12 self._ _address = address
13
14 def set_phone(self, phone):
15 self._ _phone = phone
16
17 def get_name(self):
18 return self._ _name
19
20 def get_address(self):
21 return self._ _address
22
23 def get_phone(self):
24 return self._ _phone
Car
__make
__model
__year
__init__(make, model,
year)
set_make(make)
set_model(make)
set_year(y)
get_make( )
get_model( )
get_year( )
1 # Car class
2 class Car:
3 def _ _init_ _(self, make, model, year):
4 self._ _make = make
5 self._ _model = model
6 self._ _year = year
7
8 def set_make(self, make):
9 self._ _make = make
10
11 def set_model(self, model):
12 self._ _model = model
13
14 def set_year(self, year):
15 self._ _year = year
16
17 def get_make(self):
18 return self._ _make
19
20 def get_model(self):
21 return self._ _model
22
23 def get_year(self):
24 return self._ _year
ServiceQuote
__parts_charges
__labor_charges
__init__(pcharge, lcharge)
set_parts_charges(pcharge)
set_labor_charges(lcharge)
get_parts_charges( )
get_labor_charges( )
get_sales_tax( )
get_total_charges( )
25 def get_total_charges(self):
26 return _ _parts_charges + _ _labor_charges + \
27 (_ _parts_charges * TAX_RATE)
Checkpoint
10.15 The typical UML diagram for a class has three sections. What appears in these
three sections?
10.16 What is a problem domain?
10.17 When designing an object-oriented application, who should write a description of
the problem domain?
10.18 How do you identify the potential classes in a problem domain description?
10.19 What are a class’s responsibilities?
10.20 What two questions should you ask to determine a class’s responsibilities?
10.21 Will all of a class’s actions always be directly mentioned in the problem domain
description?
Review Questions
Multiple Choice
1. The ______________ programming practice is centered on creating functions that are
separate from the data that they work on.
a. modular
b. procedural
c. functional
d. object-oriented
2. The ______________ programming practice is centered on creating objects.
a. object-centric
b. objective
c. procedural
d. object-oriented
11. In one approach to identifying the classes in a problem, the programmer identifies the
______________ in a description of the problem domain.
a. verbs
b. adjectives
c. adverbs
d. nouns
12. In one approach to identifying a class’s data attributes and methods, the programmer
identifies the class’s ______________.
a. responsibilities
b. name
c. synonyms
d. nouns
True or False
1. The practice of procedural programming is centered on the creation of objects.
2. Object reusability has been a factor in the increased use of object-oriented programming.
3. It is a common practice in object-oriented programming to make all of a class’s data
attributes accessible to statements outside the class.
4. A class method does not have to have a self parameter.
5. Starting an attribute name with two underscores will hide the attribute from code
outside the class.
6. You cannot directly call the _ _str_ _ method.
7. One way to find the classes needed for an object-oriented program is to identify all of
the verbs in a description of the problem domain.
Short Answer
1. What is meant by data hiding?
2. How are an object’s data attributes made inaccessible to code outside the class definition?
3. What is the difference between a class and an instance of a class?
4. The following statement calls an object’s method. What is the name of the method?
What is the name of the variable that references the object?
wallet.get_dollar()
5. When the _ _init_ _ method executes, what does the self parameter reference?
6. In a Python class, how do you hide an attribute from code outside the class?
7. The _ _str_ _ method in Python returns a string representation of an object’s state.
Describe how the _ _str_ _ method is used to print the state of an object.
Algorithm Workbench
1. Write a definition for a class Book. The Book class has data attributes for a title, an
author name, and the number of pages. The class also has the following methods:
a. An _ _init_ _ method for the class. The method should accept arguments for each
of the data attributes.
b. A special _ _len_ _ method to return the number of pages in the book.
c. An _ _str_ _ method that returns a string showing the state of the object.
2. Write a class definition named Book. The Book class should have data attributes for a
book’s title, the author’s name, and the publisher’s name. The class should also have
the following:
a. An _ _init_ _ method for the class. The method should accept an argument for
each of the data attributes.
b. Accessor and mutator methods for each data attribute.
c. An _ _str_ _ method that returns a string indicating the state of the object.
3. Look at the following description of a problem domain:
The bank offers the following types of accounts to its customers: savings accounts,
checking accounts, and money market accounts. Customers are allowed to deposit
money into an account (thereby increasing its balance), withdraw money from an
account (thereby decreasing its balance), and earn interest on the account. Each
account has an interest rate.
Assume that you are writing a program that will calculate the amount of interest
earned for a bank account.
a. Identify the potential classes in this problem domain.
b. Refine the list to include only the necessary class or classes for this problem.
c. Identify the responsibilities of the class or classes.
Programming Exercises
1. Pet Class
VideoNote
Write a class named Pet, which should have the following data attributes:
The Pet class
• _ _name (for the name of a pet)
• _ _animal_type (for the type of animal that a pet is. Example values are ‘Dog’, ‘Cat’,
and ‘Bird’)
• _ _age (for the pet’s age)
The Pet class should have an _ _init_ _ method that creates these attributes. It should also
have the following methods:
• set_name
This method assigns a value to the _ _name field.
• set_animal_type
This method assigns a value to the _ _animal_type field.
• set_age
This method assigns a value to the _ _age field.
• get_name
This method returns the value of the _ _ name field.
• get_animal_type
This method returns the value of the _ _animal_type field.
• get_age
This method returns the value of the _ _age field.
Once you have written the class, write a program that creates an object of the class and
prompts the user to enter the name, type, and age of his or her pet. This data should be
stored as the object’s attributes. Use the object’s accessor methods to retrieve the pet’s
name, type, and age and display this data on the screen.
2. Car Class
Write a class named Car that has the following data attributes:
• _ _year_model (for the car’s year model)
• _ _make (for the make of the car)
• _ _speed (for the car’s current speed)
The Car class should have an _ _init_ _ method that accepts the car’s year model and
make as arguments. These values should be assigned to the object’s _ _year_model and
_ _make data attributes. It should also assign 0 to the _ _speed data attribute.
The class should also have the following methods:
• accelerate
The accelerate method should add 5 to the speed data attribute each time it is called.
• brake
The brake method should subtract 5 from the speed data attribute each time it is called.
• get_speed
The get_speed method should return the current speed.
Next, design a program that creates a Car object then calls the accelerate method five
times. After each call to the accelerate method, get the current speed of the car and dis-
play it. Then call the brake method five times. After each call to the brake method, get the
current speed of the car and display it.
3. Personal Information Class
Design a class that holds the following personal data: name, address, age, and phone num-
ber. Write appropriate accessor and mutator methods. Also, write a program that creates
three instances of the class. One instance should hold your information, and the other two
should hold your friends’ or family members’ information.
4. Employee Class
Write a class named Employee that holds the following data about an employee in attrib-
utes: name, ID number, department, and job title.
Once you have written the class, write a program that creates three Employee objects to
hold the following data:
The program should store this data in the three objects, then display the data for each
employee on the screen.
5. RetailItem Class
Write a class named RetailItem that holds data about an item in a retail store. The class
should store the following data in attributes: item description, units in inventory, and price.
Once you have written the class, write a program that creates three RetailItem objects
and stores the following data in them:
6. Patient Charges
Write a class named Patient that has attributes for the following data:
• First name, middle name, and last name
• Address, city, state, and ZIP code
• Phone number
• Name and phone number of emergency contact
The Patient class’s _ _init_ _ method should accept an argument for each attribute. The
Patient class should also have accessor and mutator methods for each attribute.
Next, write a class named Procedure that represents a medical procedure that has been
performed on a patient. The Procedure class should have attributes for the following data:
• Name of the procedure
• Date of the procedure
• Name of the practitioner who performed the procedure
• Charges for the procedure
The Procedure class’s _ _init_ _ method should accept an argument for each attribute.
The Procedure class should also have accessor and mutator methods for each attribute.
Next, write a program that creates an instance of the Patient class, initialized with sample
data. Then, create three instances of the Procedure class, initialized with the following data:
The program should display the patient’s information, information about all three of the
procedures, and the total charges of the three procedures.
To create this program, write a Question class to hold the data for a trivia question. The
Question class should have attributes for the following data:
• A trivia question
• Possible answer 1
• Possible answer 2
• Possible answer 3
• Possible answer 4
• The number of the correct answer (1, 2, 3, or 4)
The Question class also should have an appropriate _ _init_ _ method, accessors, and
mutators.
The program should have a list or a dictionary containing 10 Question objects, one for
each trivia question. Make up your own trivia questions on the subject or subjects of your
choice for the objects.