Chapter 23

Writing Classes

No programming language can anticipate all data types that a programmer might eventually need, and so object-oriented languages allow you to create new data types by defining classes. We start with a simple example to highlight the new concepts.

Listing 23.1: Sum of Dice

 1 # dicesum.py
 2
 3 from random import randint
 4
 5 class Die:
 6 def __init__(self):
 7  self.roll()
 8
 9 def roll(self):
10 self.value = randint(1, 6)
11
12 def __str__(self):
13  return str(self.value)
14
15 def main():
16 rolls = int(input("Enter the number of times to roll: "))
17 die1 = Die()
18 die2 = Die()
19 counts = [0] * 13
20 for i in range(rolls):
21  die1.roll()
22  die2.roll()
23  counts[die1.value + die2.value] += 1
24 for i in range(2, 13):
25  print(str(i) + ": " + str(counts[i]))
26
27 main()

Object-Oriented Terminology

As we learn to create our own data types, it will help to have a clear understanding of the terminology:

Class A class is a template that defines objects of a new data type by specifying their state and behavior. For example, a PlayingCard class might define card objects for a game program.

Object An object is a specific instance of a class, with its own particular state. A program may create as many instances of a class as it needs. For example, a card game might create 52 PlayingCard objects to represent a deck.

State Objects have attributes or characteristics that are important to track for the purposes of a particular application. The current values of those attributes constitute the object’s state. Object state is stored in fields, sometimes more specifically referred to as instance fields. A PlayingCard might have fields to store its rank and suit.

Behavior Objects will also have behaviors that need to be modeled by an application. Object behaviors are described by methods. For example, a CardDeck class might define a shuffle() method.

Methods are called mutators if they change the state of the object or accessors if they only return information about the state.

Constructor Constructors are called to create new objects. Each class will have its own constructor.

Remember that all data types in Python are object data types and so are defined by classes. What is different now is that we are writing classes to create new data types of our own.

Class Definitions

Classes are used to help manage the complexity that comes with building larger, more realistic programs. All class definitions begin with one line:

class <ClassName>:
 <body>

Class names are capitalized. In case you have been wondering, that is why we never capitalize function or variable names (except for all-caps constants). The body of a class definition contains all of its field and method definitions.

Field Definitions

Python is unusual in that it does not use explicit field declarations. In other words, you may have to search carefully in order to find all of the fields in a class definition. Fields are defined within the class by giving a value to a variable whose name begins with “self.” (notice the dot). That is, any variable whose name begins with “self.” is a field that is stored within the object. Every object has its own separate storage location for its fields, so that objects can hold different values in each of their fields.

Method Definitions

Methods are defined inside the body of a class in the same way as functions, using def, except that the first parameter for every method should be a variable named self. In other words, only two things distinguish an instance method from a regular function:

  1. The def appears inside the body of a class.
  2. The first parameter is self.

Method Calls Inside a Class

As you develop code for a class, you will often find it necessary for one instance method to call another instance method inside the class implementation. Python uses the same syntax for these method calls as it does for referencing an instance field: the method name must be prefaced with “self.” For example, the __init__() method of the Die class calls the roll() method on line 7 like this:

 self.roll()

If you omit “self.,” Python will assume that you are calling a regular function rather than an instance method.

Special Methods: __init__() and __str()__

In Python, methods with names that start and end with two underscores (__) will be called automatically in certain situations. Every class should define an __init__() method to give appropriate initial values to its instance fields. This is called initializing the object. In other words, __init__() is called automatically whenever the constructor creates a new object.

Most classes should also define a __str__() method, which is called any time the object appears in a print() or as an argument to str(). The __str__() method should return a string that describes the object. This doesn’t necessarily mean including everything that is known about the object, but there should be enough information included to reasonably represent the object.

Calling Constructors

As mentioned above, constructors are used to create new objects. The syntax to call a constructor in Python is:

<ClassName>(<parameters>)

The constructor for a class always has the same name as the class itself. Any parameters sent to the constructor are passed on to the class’s __init__() method.

When calling a constructor, we almost always immediately store the new object in a variable; otherwise, the object would reside in memory with no way to access it.

Exercises

  1. 23.1 Use Listing 23.1 to answer these questions:
    1. (a) What state is stored in the Die class? Explain how you know.
    2. (b) What behaviors are defined by the Die class? Explain how you know.
  2. 23.2 Use Listing 23.1 to answer these questions:
    1. (a) Identify all instance fields in the Die class. Explain how you found them.
    2. (b) Identify all instance methods in the Die class. Explain how you found them.
    3. (c) For each method found in the previous question, indicate whether it is a mutator or accessor. Explain your answers.
    4. (d) Identify all calls to the Die() constructor. How many instances are created, and where are the new objects stored?
    5. (e) The __init__() method should “give appropriate initial values to its instance fields.” Explain how the __init__() method of the Die class does this.
  3. 23.3 Explain the need for the calls to str() in line 25 of Listing 23.1.
  4. 23.4 Explain the use of the number “13” in lines 19 and 24 of Listing 23.1.
  5. 23.5 Rewrite Listing 23.1 to not use a Die class. Discuss the tradeoffs.
  6. 23.6 Modify Listing 23.1 to sum three dice instead of two.
  7. 23.7 Modify Listing 23.1 to sum n dice instead of two. Ask the user for the value of n.
  8. 23.8 Not all dice are cubes with 6 sides. There are dice for each of the platonic solids, as well as some other shapes. Modify the Die class to represent dice with different numbers of sides, and then modify Listing 23.1 to ask the user for the number of sides on the dice that will be simulated. Use a default value of 6 for the number of sides in the Die constructor.
  9. 23.9 Imagine writing a Student class for a registration system.
    1. (a) List some elements that should be included in the Student’s state.
    2. (b) List some possible behaviors that the Student object may need to perform.
  10. 23.10 Imagine writing a Course class for a registration system.
    1. (a) List some elements that should be included in the Course’s state.
    2. (b) List some possible behaviors that the Course object may need to perform.
  11. 23.11 Imagine writing an Instructor class for a registration system.
    1. (a) List some elements that should be included in the Instructor’s state.
    2. (b) List some possible behaviors that the Instructor object may need to perform.
  12. 23.12 Imagine writing an Employee class for a human resources system.
    1. (a) List some elements that should be included in the Employee’s state.
    2. (b) List some possible behaviors that the Employee object may need to perform.
  13. 23.13 Imagine writing a Department class for a human resources system.
    1. (a) List some elements that should be included in the Department’s state.
    2. (b) List some possible behaviors that the Department object may need to perform.
  14. 23.14 Write a Circle class that represents a circle. Store the radius of the circle, and include methods that return the circle’s area and circumference. Write a main() function that creates a few circles and prints each area and circumference. (You do not need to write a __str__() method.)
  15. 23.15 Write a Vector class that represents a two-dimensional vector (x, y). Include a __str__() method, as well as a norm() method that returns the length of the vector, x2+y2 . Write a main() function to test your code.
  16. 23.16 Write an RGB class that represents an RGB color. Store the red, green, and blue components. Include a __str__() method and a luminance() method that returns the luminance of the color. Write a main() function to test your code.
  17. 23.17 Write a CD class that represents a single music cd. Store the artist, title, genre, year of release, and playing time in minutes and seconds. However, instead of providing all of these as parameters to __init__(), write your class so that only the artist and title are passed to the constructor. Set the other fields to None initially, but provide setyear(), setgenre(), and setplayingtime() methods so that they can be set later. Have the __str__() method return the artist, title, and year, but only include the year if it was previously set. Write a main() function to test your code.
  18. 23.18 Write a Card class that represents a single playing card from a standard 52-card deck. Each card has a numeric rank and a suit that is hearts, diamonds, spades, or clubs. Include a __str()__ method that returns a string representation of the card. Write a main() function that creates all 52 cards, shuffles them, and then prints the cards in shuffled order.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.199.122