0% found this document useful (0 votes)
15 views107 pages

Python Class Definitions and Simulation

Introduction to Python Programming

Uploaded by

doctorvega70
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views107 pages

Python Class Definitions and Simulation

Introduction to Python Programming

Uploaded by

doctorvega70
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd

Python Programming:

An Introduction To
Computer Science

Chapter 10
Defining Classes

Python Programming, 1/e 1


Objectives
 To appreciate how defining new
classes can provide structure for a
complex program.
 To be able to read and write
Python class definitions.
 To understand the concept of
encapsulation and how it
contributes to building modular
and maintainable programs.
Python Programming, 1/e 2
Objectives
 To be able to write programs
involving simple class definitions.
 To be able to write interactive
graphics programs involving novel
(programmer designed) widgets.

Python Programming, 1/e 3


Quick Review of Objects
 In the last three chapters we’ve developed
techniques for structuring the computations
of the program.
 We’ll now take a look at techniques for
structuring the data that our programs use.
 So far, our programs have made use of
objects created from pre-defined class such
as Circle. In this chapter we’ll learn how to
write our own classes to create novel
objects.

Python Programming, 1/e 4


Quick Review of Objects
 In chapter five an object was
defined as an active data type
that knows stuff and can do stuff.
 More precisely, an object consists
of:
1. A collection of related information.
2. A set of operations to manipulate
that information.
Python Programming, 1/e 5
Quick Review of Objects
 The information is stored inside
the object in instance variables.
 The operations, called methods,
are functions that “live” inside the
object.
 Collectively, the instance variables
and methods are called the
attributes of an object.
Python Programming, 1/e 6
Quick Review of Objects
 A Circle object will have instance
variables such as center, which
remembers the center point of the
circle, and radius, which stores the
length of the circle’s radius.
 The draw method examines the
center and radius to decide which
pixels in a window should be colored.

Python Programming, 1/e 7


Quick Review of Objects
 The move method will change the
value of center to reflect the new
position of the circle.
 All objects are said to be an
instance of some class. The class
of an object determines which
attributes the object will have.
 A class is a description of what its
instances will know and do.
Python Programming, 1/e 8
Quick Review of Objects
 New objects are created from a class
by invoking a constructor. You can
think of the class itself as a sort of
factory for stamping out new
instances.
 Consider making a new circle object:
myCircle = Circle(Point(0,0),20)
 Circle, the name of the class, is used
to invoke the constructor.
Python Programming, 1/e 9
Quick Review of Objects
myCircle = Circle(Point(0,0), 20)
 This statement creates a new Circle
instance and stores a reference to it
in the variable myCircle.
 The parameters to the constructor
are used to initialize some of the
instance variables (center and
radius) inside myCircle.

Python Programming, 1/e 10


Quick Review of Objects
myCircle = Circle(Point(0,0), 20)
 Once the instance has been
created, it can be manipulated by
calling on its methods:
[Link](win)
[Link](dx,dy)

Python Programming, 1/e 11


Cannonball Program
Specification
 Let’s try to write a program that
simulates the flight of a cannonball
or other projectile.
 We’re interested in how far the
cannonball will travel when fired at
various launch angles and initial
velocities.

Python Programming, 1/e 12


Cannonball Program
Specification
 The input to the program will be
the launch angle (in degrees), the
initial velocity (in meters per
second), and the initial height (in
meters) of the cannonball.
 The output will be the distance
that the projectile travels before
striking the ground (in meters).
Python Programming, 1/e 13
Cannonball Program
Specification
 The acceleration of gravity near the
earth’s surface is roughly 9.8 m/s/s.
 If an object is thrown straight up at
20 m/s, after one second it will be
traveling upwards at 10.2 m/s. After
another second, its speed will be .4
m/s. Shortly after that the object will
start coming back down to earth.

Python Programming, 1/e 14


Cannonball Program
Specification
 Using calculus, we could derive a
formula that gives the position of the
cannonball at any moment of its flight.
 However, we’ll solve this problem with
simulation, a little geometry, and the
fact that the distance an object travels
in a certain amount of time is equal to
its rate times the amount of time
(d = rt).

Python Programming, 1/e 15


Designing the Program
 Given the nature of the problem, it’s
obvious we need to consider the flight
of the cannonball in two dimensions:
it’s height and the distance it travels.
 Let’s think of the position of the
cannonball as the point (x, y) where x
is the distance from the starting point
and y is the height above the ground.

Python Programming, 1/e 16


Designing the Program
 Suppose the ball starts at position
(0,0), and we want to check its
position every tenth of a second.
 In that time interval it will have
moved some distance upward
(positive y) and some distance
forward (positive x). The exact
distance will be determined by the
velocity in that direction.
Python Programming, 1/e 17
Designing the Program
 Since we are ignoring wind
resistance, x will remain constant
through the flight.
 However, y will change over time
due to gravity. The y velocity will
start out positive and then become
negative as the ball starts to fall.

Python Programming, 1/e 18


Designing the Program
 Input the simulation parameters: angle,
velocity, height, interval.
 Calculate the initial position of the
cannonball: xpos, ypos
 Calculate the initial velocities of the
cannonball: xvel, yvel
 While the cannonball is still flying:
 Update the values of xpos, ypos, and yvel
for interval seconds further into the flight
 Output the distance traveled as xpos

Python Programming, 1/e 19


Designing the Program
 Using step-wise refinement:
def main():
angle = input("Enter the launch angle (in degrees): ")
vel = input("Enter the initial velocity (in meters/sec): ")
h0 = input("Enter the initial height (in meters): ")
time = input("Enter the time interval between position calculations: ")

 Calculating the initial position for


the cannonball is also easy. It’s at
distance 0 and height h0!
xpos = 0
ypos = h0

Python Programming, 1/e 20


Designing the Program

 If we know the magnitude of the velocity


and the angle theta, we can calculate
yvel=velocity*sin(theta)and
xvel=velocity*cos(theta).

Python Programming, 1/e 21


Designing the Program
 Our input angle is in degrees, and the
Python math library uses radians, so theta
= (*angle)/180.
 theta = (angle * pi)/180.0
xvel = vel * cos(theta)
yvel = vel * sin(theta)
 In the main loop, we want to keep
updating the position of the ball until it
reaches the ground:
while ypos >= 0.0:
 We used >= 0 so the loop will start if the
ball starts out on the ground.
Python Programming, 1/e 22
Designing the Program
 Each time through the loop we want to
update the state of the cannonball to move
it time seconds farther.
 Since we assume there is no wind
resistance, xvel remains constant.
 Say a ball is traveling at 30 m/s and is 50 m
from the firing point. In one second it will
be 50 + 30 meters away. If the time
increment is .1 second it will be 50 + 30*.1
= 53 meters.
 xpos = xpos + time * xvel
Python Programming, 1/e 23
Designing the Program
 Working with yvel is slightly more
complicated since gravity causes
the y-velocity to change over time.
 Each second, yvel must decrease
by 9.8 m/s, the acceleration due to
gravity.
 In 0.1 seconds the velocity will be
0.1(9.8) = .98 m/s.
 yvel1 = yvel - 9.8 * time
Python Programming, 1/e 24
Designing the Programs
 To calculate how far the cannonball
travels over the interval, we need to
calculate its average vertical velocity
over the interval.
 Since the velocity due to gravity is
constant, it is simply the average of the
starting and ending velocities times the
length of the interval:
ypos = ypos + time * (yvel + yvel1)/2.0

Python Programming, 1/e 25


Designing Programs
# [Link]
# Simulation of the flight of a cannon ball (or other projectile)
# This version is not modularized.

from math import pi, sin, cos

def main():
angle = input("Enter the launch angle (in degrees): ")
vel = input("Enter the initial velocity (in meters/sec): ")
h0 = input("Enter the initial height (in meters): ")
time = input("Enter the time interval between position calculations: ")

radians = (angle * pi)/180.0


xpos = 0
ypos = h0
xvel = vel * cos(radians)
yvel = vel * sin(radians)
while ypos >= 0:
xpos = xpos + time * xvel
yvel1 = yvel - 9.8 * time
ypos = ypos + time * (yvel + yvel1)/2.0
yvel = yvel1

print "\nDistance traveled: %0.1f meters." % (xpos)

main()

Python Programming, 1/e 26


Modularizing the Program
 During program development, we
employed step-wise refinement
(and top-down design), but did not
divide the program into functions.
 While this program is fairly short, it
is complex due to the number of
variables.

Python Programming, 1/e 27


Modularizing the Program
def main():
angle, vel, h0, time = getInputs()
xpos, ypos = 0, h0
xvel, yvel = getXYComponents(vel, angle)
while ypos >= 0:
xpos, ypos, yvel = updateCannonBall(time, xpos, ypos, xvel, yvel)

print "\nDistance traveled: %0.1f meters." % (xpos)

 It should be obvious what each of


these helper functions does based
on their name and the original
program code.
Python Programming, 1/e 28
Modularizing the Program
 This version of the program is more
concise!
 The number of variables has been reduced
from 10 to 8, since theta and yvel1 are
local to getXYComponents and
updateCannonBall, respectively.
 This may be simpler, but keeping track of
the cannonball still requires four pieces of
information, three of which change from
moment to moment!
Python Programming, 1/e 29
Modularizing the Program
 All four variables, plus time, are
needed to compute the new values
of the three that change.
 This gives us a function with five
parameters and three return
values.
 Yuck! There must be a better way!

Python Programming, 1/e 30


Modularizing the Program
 There is a single real-world cannonball
object, but it requires four pieces of
information: xpos, ypos, xvel,x and
yvel.
 Suppose there was a Projectile class
that “understood” the physics of objects
like cannonballs. An algorithm using this
approach would create and update an
object stored in a single variable.

Python Programming, 1/e 31


Modularizing the Program
 Using our object-based approach:
def main():
angle, vel, h0, time = getInputs()
cball = Projectile(angle, vel, h0)
while [Link]() >= 0:
[Link](time)
print "\nDistance traveled: %0.1f meters." % ([Link]())
main()

 To make this work we need a


Projectile class that implements
the methods update, getX, and
getY.
Python Programming, 1/e 32
Example: Multi-Sided Dice
 A normal die (singular of dice) is a
cube with six faces, each with a
number from one to six.
 Some games use special dice with
a different number of sides.
 Let’s design a generic class MSDie
to model multi-sided dice.

Python Programming, 1/e 33


Example: Multi-Sided Dice
 Each MSDie object will know two
things:
 How many sides it has.
 It’s current value
 When a new MSDie is created, we
specify n, the number of sides it
will have.

Python Programming, 1/e 34


Example: Multi-Sided Dice
 We have three methods that we
can use to operate on the die:
 roll – set the die to a random value
between 1 and n, inclusive.
 setValue – set the die to a specific
value (i.e. cheat)
 getValue – see what the current
value is.

Python Programming, 1/e 35


Example: Multi-Sided Dice
>>> die1 = MSDie(6)
>>> [Link]()
1
>>> [Link]()
>>> [Link]()
5
>>> die2 = MSDie(13)
>>> [Link]()
1
>>> [Link]()
>>> [Link]()
9
>>> [Link](8)
>>> [Link]()
8

Python Programming, 1/e 36


Example: Multi-Sided Dice
 Using our object-oriented vocabulary, we
create a die by invoking the MSDie constructor
and providing the number of sides as a
parameter.
 Our die objects will keep track of this number
internally as an instance variable.
 Another instance variable is used to keep the
current value of the die.
 We initially set the value of the die to be 1
because that value is valid for any die.
 That value can be changed by the roll and
setRoll methods, and returned by the
getValue method.
Python Programming, 1/e 37
Example: Multi-Sided Dice
# [Link]
# Class definition for an n-sided die.

from random import randrange

class MSDie:

def __init__(self, sides):


[Link] = sides
[Link] = 1

def roll(self):
[Link] = randrange(1, [Link]+1)

def getValue(self):
return [Link]

def setValue(self, value):


[Link] = value

Python Programming, 1/e 38


Example: Multi-Sided Dice
 Class definitions have the form
class <class-name>:
<method-definitions>
 Methods look a lot like functions! Placing
the function inside a class makes it a
method of the class, rather than a stand-
alone function.
 The first parameter of a method is always
named self, which is a reference to the
object on which the method is acting.

Python Programming, 1/e 39


Example: Multi-Sided Dice
 Suppose we have a main function that
executes [Link](8).
 Just as in function calls, Python executes
the following four-step sequence:
 main suspends at the point of the method
application. Python locates the appropriate
method definition inside the class of the
object to which the method is being applied.
Here, control is transferred to the setValue
method in the MSDie class, since die1 is an
instance of MSDie.

Python Programming, 1/e 40


Example: Multi-Sided Dice
 The formal parameters of the method
get assigned the values supplied by
the actual parameters of the call. In
the case of a method call, the first
formal parameter refers to the object:
self = die1
value = 8
 The body of the method is executed.

Python Programming, 1/e 41


Example: Multi-Sided Dice
 Control returns to the point just after
where the method was called. In this
case, it is immediately following
[Link](8).
 Methods are called with one
parameter, but the method
definition itself includes the self
parameter as well as the actual
parameter.
Python Programming, 1/e 42
Example: Multi-Sided Dice
 The self parameter is a
bookkeeping detail. We can refer
to the first formal parameter as the
self parameter and other
parameters as normal parameters.
So, we could say setValue uses
one normal parameter.

Python Programming, 1/e 43


Example: Multi-Sided Dice

Python Programming, 1/e 44


Example: Multi-Sided Dice
 Objects contain their own data. Instance
variables provide storage locations
inside of an object.
 Instance variables are accessed by
name using our dot notation:
<object>.<instance-var>
 Looking at setValue, we see
[Link] refers to the instance
variable value inside the object. Each
MSDie object has its own value.
Python Programming, 1/e 45
Example: Multi-Sided Dice
 Certain methods have special
meaning. These methods have names
that start and end with two _’s.
 __init__ is the object contructor.
Python calls this method to initialize a
new MSDie. __init__ provides initial
values for the instance variables of an
object.

Python Programming, 1/e 46


Example: Multi-Sided Dice
 Outside the class, the constructor is
referred to by the class name:
die1 = MSDie(6)
 When this statement is executed, a
new MSDie object is created and
__init__ is executed on that object.
 The net result is that [Link] is
set to 6 and [Link] is set to 1.

Python Programming, 1/e 47


Example: Multi-Sided Dice
 Instance variables can remember
the state of a particular object, and
this information can be passed
around the program as part of the
object.
 This is different than local function
variables, whose values disappear
when the function terminates.
Python Programming, 1/e 48
Example: The Projectile
Class
 This class will need a constructor to
initialize instance variables, an update
method to change the state of the
projectile, and getX and getY methods
that can report the current position.
 In the main program, a cannonball can
be created from the initial angle,
velocity, and height:
cball = Projectile(angle, vel, h0)

Python Programming, 1/e 49


Example: The Projectile
Class
 The Projectile class must have
an __init__ method that will use
these values to initialize the
instance variables of cball.
 These values will be calculated
using the same formulas as before.

Python Programming, 1/e 50


Example: The Projectile
Class
class Projectile:

def __init__(self, angle, velocity, height):


[Link] = 0.0
[Link] = height
theta = pi * angle / 180.0
[Link] = velocity * cos(theta)
[Link] = velocity * sin(theta)

 We’ve created four instance variables


(self.???). Since the value of theta is
not needed later, it is a normal function
value.

Python Programming, 1/e 51


Example: The Projectile
Class
 The methods to access the X and Y
position are straightforward.

def getY(self):
return [Link]

def getX(self):
return [Link]

Python Programming, 1/e 52


Example: The Projectile
Class
 The last method is update, where
we’ll take the time interval and
calculate the update X and Y values.
def update(self, time):
[Link] = [Link] + time * [Link]
yvel1 = [Link] - 9.8 * time
[Link] = [Link] + time * ([Link] + yvel1) / 2.0
[Link] = yvel1

 yvel1 is a temporary variable.

Python Programming, 1/e 53


Data Processing with Class
 A class is useful for modeling a real-
world object with complex behavior.
 Another common use for objects is to
group together a set of information that
describes a person or thing.
 Eg., a company needs to keep track of
information about employees (an Employee
class with information such as employee’s
name, social security number, address,
salary, etc.)
Python Programming, 1/e 54
Data Processing with Class
 Grouping information like this is often
called a record.
 Let’s try a simple data processing
example!
 A typical university measures courses
in terms of credit hours, and grade
point averages are calculated on a 4
point scale where an “A” is 4 points, a
“B” is three, etc.
Python Programming, 1/e 55
Data Processing with Class
 Grade point averages are generally
computed using quality points. If a
class is worth 3 credit hours and the
student gets an “A”, then he or she
earns
3(4) = 12 quality points. To calculate
the GPA, we divide the total quality
points by the number of credit hours
completed.
Python Programming, 1/e 56
Data Processing with Class
 Suppose we have a data file that
contains student grade
information.
 Each line of the file consists of a
student’s name, credit-hours, and
quality points.
Adams, Henry 127 228
Comptewell, Susan 100 400
DibbleBit, Denny 18 41.5
Jones, Jim 48.5 155
Smith, Frank 37 125.33

Python Programming, 1/e 57


Data Processing with Class
 Our job is to write a program that
reads this file to find the student
with the best GPA and print out
their name, credit-hours, and GPA.
 The place to start? Creating a
Student class!
 We can use a Student object to
store this information as instance
variables.
Python Programming, 1/e 58
Data Processing with Class
 class Student:
def __init__(self, name, hours, qpoints):
[Link] = name
[Link] = float(hours)
[Link] = float(qpoints)
 The values for hours are converted to
float to handle parameters that may
be floats, ints, or strings.
 To create a student record:
aStudent = Student(“Adams, Henry”, 127, 228)
 The coolest thing is that we can store all
the information about a student in a
single variable!

Python Programming, 1/e 59


Data Processing with Class
 We need to be able to access this information,
so we need to define a set of accessor
methods.
 def getName(self):
return [Link]
def getHours(self):
return [Link]
def getQPoints(self):
return [Link]
def gpa(self):
return [Link]/[Link]
 For example, to print a student’s name you
could write:
print [Link]()

Python Programming, 1/e 60


Data Processing with Class
 How can we use these tools to find
the student with the best GPA?
 We can use an algorithm similar to
finding the max of n numbers! We
could look through the list one by
one, keeping track of the best
student seen so far!

Python Programming, 1/e 61


Data Processing with Class
Get the file name from the user
Open the file for reading
Set best to be the first student
For each student s in the file
if [Link]() > [Link]
set best to s
Print out information about best

Python Programming, 1/e 62


Data Processing with Class
# [Link] def main():
# Program to find student with highest GPA filename = raw_input("Enter name the grade file: ")
import string infile = open(filename, 'r')
best = makeStudent([Link]())
class Student: for line in infile:
s = makeStudent(line)
def __init__(self, name, hours, qpoints): if [Link]() > [Link]():
[Link] = name best = s
[Link] = float(hours) [Link]()
[Link] = float(qpoints) print "The best student is:", [Link]()
print "hours:", [Link]()
def getName(self): print "GPA:", [Link]()
return [Link]
if __name__ == '__main__':
def getHours(self): main()
return [Link]

def getQPoints(self):
return [Link]

def gpa(self):
return [Link]/[Link]

def makeStudent(infoStr):
name, hours, qpoints = [Link](infoStr,"\t")
return Student(name, hours, qpoints)

Python Programming, 1/e 63


Encapsulating Useful
Abstractions
 Defining new classes (like
Projectile and Student) can be a
good way to modularize a program.
 Once some useful objects are
identified, the implementation
details of the algorithm can be
moved into a suitable class
definition.
Python Programming, 1/e 64
Encapsulating Useful
Abstractions
 The main program only has to worry
about what objects can do, not about
how they are implemented.
 In computer science, this separation of
concerns is known as encapsulation.
 The implementation details of an object
are encapsulated in the class definition,
which insulates the rest of the program
from having to deal with them.
Python Programming, 1/e 65
Encapsulating Useful
Abstractions
 One of the main reasons to use
objects is to hide the internal
complexities of the objects from
the programs that use them.
 From outside the class, all
interaction with an object can be
done using the interface provided
by its methods.
Python Programming, 1/e 66
Encapsulating Useful
Abstractions
 One advantage of this approach is
that it allows us to update and
improve classes independently
without worrying about “breaking”
other parts of the program,
provided that the interface
provided by the methods does not
change.
Python Programming, 1/e 67
Putting Classes in Modules
 Sometimes we may program a class
that could useful in many other
programs.
 If you might be reusing the code
again, put it into its own module file
with documentation to describe how
the class can be used so that you
won’t have to try to figure it out in the
future from looking at the code!
Python Programming, 1/e 68
Module Documentation
 You are already familiar with “#” to
indicate comments explaining what’s
going on in a Python file.
 Python also has a special kind of
commenting convention called the
docstring. You can insert a plain string
literal as the first line of a module,
class, or function to document that
component.
Python Programming, 1/e 69
Module Documentation
 Why use a docstring?
 Ordinary comments are ignored by Python
 Docstrings are accessible in a special
attribute called __doc__.
 Most Python library modules have
extensive docstrings. For example, if
you can’t remember how to use random:
>>> import random
>>> print [Link].__doc__
random() -> x in the interval [0, 1).

Python Programming, 1/e 70


Module Documentation
 Docstrings are also used by the Python
online help system and by a utility
called PyDoc that automatically builds
documentation for Python modules. You
could get the same information like this:
>>> import random
>>> help([Link])
Help on built-in function random:

random(...)
random() -> x in the interval [0, 1).

Python Programming, 1/e 71


Module Documentation
 To see the documentation for an
entire module, try typing
help(module_name)!
 The following code for the
projectile class has docstrings.

Python Programming, 1/e 72


Module Documentation
# [Link]

"""[Link]
Provides a simple class for modeling the flight of projectiles."""

from math import pi, sin, cos

class Projectile:

"""Simulates the flight of simple projectiles near the earth's


surface, ignoring wind resistance. Tracking is done in two
dimensions, height (y) and distance (x)."""

def __init__(self, angle, velocity, height):


"""Create a projectile with given launch angle, initial
velocity and height."""
[Link] = 0.0
[Link] = height
theta = pi * angle / 180.0
[Link] = velocity * cos(theta)
[Link] = velocity * sin(theta)

Python Programming, 1/e 73


Module Documentation
def update(self, time):
"""Update the state of this projectile to move it time seconds
farther into its flight"""
[Link] = [Link] + time * [Link]
yvel1 = [Link] - 9.8 * time
[Link] = [Link] + time * ([Link] + yvel1) / 2.0
[Link] = yvel1

def getY(self):
"Returns the y position (height) of this projectile."
return [Link]

def getX(self):
"Returns the x position (distance) of this projectile."
return [Link]

Python Programming, 1/e 74


Working with Multiple
Modules
 Our main program can import from the
projectile module in order to solve the original
problem!
# [Link]
# Simulation of the flight of a cannon ball (or other projectile)
# This version uses a separate projectile module file
from projectile import Projectile
def getInputs():
a = input("Enter the launch angle (in degrees): ")
v = input("Enter the initial velocity (in meters/sec): ")
h = input("Enter the initial height (in meters): ")
t = input("Enter the time interval between position calculations: ")
return a,v,h,t
def main():
angle, vel, h0, time = getInputs()
cball = Projectile(angle, vel, h0)
while [Link]() >= 0:
[Link](time)
print "\nDistance traveled: %0.1f meters." % ([Link]())

Python Programming, 1/e 75


Working with Multiple
Modules
 If you are testing a multi-module Python
program, you need to be aware that reloading
a module may not behave as you expect.
 When Python first imports a given module, it
creates a module object that contains all the
things defined in the module (a namespace). If
a module imports successfully (no syntax
errors), subsequent imports do not reload the
module. Even if the source code for the
module has been changed, re-importing it into
an interactive session will not load the
updated version.

Python Programming, 1/e 76


Working with Multiple
Modules
 The easiest way – start a new
interactive session for testing
whenever any of the modules
involved in your testing are
modified. This way you’re
guaranteed to get a more recent
import of all the modules you’re
using.
Python Programming, 1/e 77
Widgets
 One very common use of objects is in
the design of graphical user interfaces
(GUIs).
 Back in chapter 5 we talked about
GUIs being composed of visual
interface objects known as widgets.
 The Entry object defined in our
graphics library is one example of a
widget.
Python Programming, 1/e 78
Example Program: Dice
Roller
 Let’s build a couple useful widgets!
 Consider a program that rolls a
pair of six-sided dice.
 The program will display the dice
graphically and provide two
buttons, one for rolling the dice
and one for quitting the program.

Python Programming, 1/e 79


Example Program: Dice
Roller
 There are two
kinds of widgets:
buttons and dice.
 The two buttons
will be examples of
the Button class,
while the dice
images will be
provided by
dieView.
Python Programming, 1/e 80
Building Buttons
 Most modern GUIs have buttons with
3-dimensional look and feel. Our
simple graphics package does not
have the machinery to produce
buttons that appear to depress as
they are clicked.
 All we can do is report back where the
mouse was clicked after the click has
been completed.
Python Programming, 1/e 81
Building Buttons
 Our buttons will be rectangular regions
in a graphics window where user clicks
can influence the behavior of the
running application.
 We need a way to determine whether
a button has been clicked.
 It would be nice to be able to activate
and deactivate (gray-out) individual
buttons.
Python Programming, 1/e 82
Building Buttons
 Constructor – Create a button in
a window. We will specify the
window, location/size of the
button, and the label on the
button.
 Activate – Set the state of the
button to active.
 Deactivate – Set the state of the
button to inactive.
Python Programming, 1/e 83
Building Buttons
 Clicked– Indicate if the button was
clicked. If the button is active, this
method will determine if the point
clicked is inside the button region. The
point will have to be sent as a
parameter to the method.
 getLabel– Returns the label string of
a button. This is provided so that we
can identify a particular button.
Python Programming, 1/e 84
Building Buttons
 To support these operations, our
buttons will need a number of
instance variables.
 For example, buttons are drawn as
a rectangle with some text centered
on it. Invoking the activate and
deactivate methods will change
the appearance of the buttons.

Python Programming, 1/e 85


Building Buttons
 Saving the Rectangle and Text objects
as instance variables means we will be
able to control the width of the outline
and color of the label.
 Let’s try writing these methods and
build up a list of possible instance
variables! Once we have the list, we
can write the constructor to initialize
them.
Python Programming, 1/e 86
Building Buttons
 In activate, we can signal a button is active by
making its outline thicker and making the label
text black.
 def activate(self):
"Sets this button to 'active'. "
[Link]('black')
[Link](2)
[Link] = True
 Remember, self refers to the button object.
 Our constructor will have to initialize [Link]
as an appropriate Text object and [Link] as a
rectangle object.
 [Link] also has a Boolean instance variable
to remember whether or not the button is
currently inactive.

Python Programming, 1/e 87


Building Buttons
 The code for deactivate is very
similar:
def deactivate(self):
"Sets this button to 'inactive'."
[Link]('darkgrey')
[Link](1)
[Link] = 0

Python Programming, 1/e 88


Building Buttons
 Let’s work on the clicked method.
 The graphics package has the
getMouse method to see if and
where the mouse has been clicked.
 If an application needs to get a
button click, it will have to first call
getMouse and then see which
button, if any, the point is inside
of.
Python Programming, 1/e 89
Building Buttons
pt = [Link]()
if [Link](pt):
# Do button1 stuff
elif [Link](pt):
# Do button2 stuff
elif [Link](pt):
# Do button3 stuff

 The main job of the clicked method


is to determine whether a given
point is inside the rectangular
button.
Python Programming, 1/e 90
Building Buttons
 The point is inside the button if its
x and y coordinates lie between
the extreme x and y values of the
rectangle.
 This would be easiest if the button
object had the min and max values
of x and y as instance variables.

Python Programming, 1/e 91


Building Buttons
 def clicked(self, p):
"RETURNS true if button active and p is inside“
return [Link] and \
[Link] <= [Link]() <= [Link] and \
[Link] <= [Link]() <= [Link]
 For this function to return True, all three
parts of the Boolean expression must be
true.
 The first part ensures that only active
buttons will return that they have been
clicked.
 The second and third parts ensure that the x
and y values of the point that was clicked fall
between the boundaries of the rectangle.
Python Programming, 1/e 92
Building Buttons
 The only part that is left is to write the
constructor:
def __init__(self, win, center, width, height, label):
""" Creates a rectangular button, eg:
qb = Button(myWin, Point(30,25), 20, 10, 'Quit') """

w,h = width/2.0, height/2.0


x,y = [Link](), [Link]()
[Link], [Link] = x+w, x-w
[Link], [Link] = y+h, y-h
p1 = Point([Link], [Link])
p2 = Point([Link], [Link])
[Link] = Rectangle(p1,p2)
[Link]('lightgray')
[Link](win)
[Link] = Text(center, label)
[Link](win)
[Link]()
 Buttons are positioned by providing a
center point, width, and height.
Python Programming, 1/e 93
Building Dice
 The purpose of the DieView class
is to graphically display the value
of a die.
 The face of the die is a
square/rectangle, and the
pips/spots on the die are circles.
 As before, the DieView class will
have a constructor and a method.
Python Programming, 1/e 94
Building Dice
 constructor – Create a die in a
window. We will specify the window,
the center point of the die, and the
size of the die as parameters.
 setValue – Change the view to show
a given value. The value to display
will be passed as a parameter.

Python Programming, 1/e 95


Building Dice
 Clearly, the hardest part of this will be
to turn on the pips on the die to
represent the current value of the die.
 One approach is to pre-place the pips,
and make them the same color as the
die. When the spot is turned on, it will
be redrawn with a darker color.

Python Programming, 1/e 96


Building Dice
 A standard die will need seven pips
-- a column of three on the left and
right sides, and one in the center.
 The constructor will create the
background square and the seven
circles. setValue will set the colors
of the circles based on the value of
the die.
Python Programming, 1/e 97
Building Dice
# [Link]
# A widget for displaying the value of a die

from graphics import *

class DieView:
""" DieView is a widget that displays a graphical representation
of a standard six-sided die."""

def __init__(self, win, center, size):


"""Create a view of a die, e.g.:
d1 = GDie(myWin, Point(40,50), 20)
creates a die centered at (40,50) having sides
of length 20."""

# first defind some standard values


[Link] = win
[Link] = "white" # color of die face
[Link] = "black" # color of the pips
[Link] = 0.1 * size # radius of each pip
hsize = size / 2.0 # half of size
offset = 0.6 * hsize # distance from center to outer pip

Python Programming, 1/e 98


Building Dice
# create a square for the face
cx, cy = [Link](), [Link]()
p1 = Point(cx-hsize, cy-hsize)
p2 = Point(cx+hsize, cy+hsize)
rect = Rectangle(p1,p2)
[Link](win)
[Link]([Link])

# Create 7 circles for standard pip locations


self.pip1 = self.__makePip(cx-offset, cy-offset)
self.pip2 = self.__makePip(cx-offset, cy)
self.pip3 = self.__makePip(cx-offset, cy+offset)
self.pip4 = self.__makePip(cx, cy)
self.pip5 = self.__makePip(cx+offset, cy-offset)
self.pip6 = self.__makePip(cx+offset, cy)
self.pip7 = self.__makePip(cx+offset, cy+offset)

[Link](1)

Python Programming, 1/e 99


Building Dice
def __makePip(self, x, y):
"""Internal helper method to draw a pip at (x,y)"""
pip = Circle(Point(x,y), [Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])
return pip

def setValue(self, value):


""" Set this die to display value."""
# turn all pips off
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])

Python Programming, 1/e 100


Building Dice
# turn correct pips on
if value == 1:
[Link]([Link])
elif value == 2:
[Link]([Link])
[Link]([Link])
elif value == 3:
[Link]([Link])
[Link]([Link])
[Link]([Link])
elif value == 4:
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])
elif value == 5:
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])
else:
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])
[Link]([Link])

Python Programming, 1/e 101


Building Dice
 Things to notice:
 The size of the spots being 1/10 of the size
of the die was determined by trial and error.
 We define and calculate various attributes
of the die in the constructor and then use
them in other methods and functions within
the class so that if we wanted to change the
appearance, all those values and the code
to go with them is in one place, rather than
throughout the class.

Python Programming, 1/e 102


Building Dice
 __makePip is a helper function to
draw each of the seven pips on the
die. Since it is only useful within
DieView, it’s appropriate to make it a
class method. It’s name starts with __
to indicate that its use is “private” to
the class and is not intended to be
used outside the class.

Python Programming, 1/e 103


The Main Program
# [Link]
# Graphics program to roll a pair of dice. Uses custom widgets
# Button and GDie.

from random import randrange


from graphics import GraphWin, Point

from button import Button


from dieview import DieView

def main():

# create the application window


win = GraphWin("Dice Roller")
[Link](0, 0, 10, 10)
[Link]("green2")

# Draw the interface widgets


die1 = DieView(win, Point(3,7), 2)
die2 = DieView(win, Point(7,7), 2)
rollButton = Button(win, Point(5,4.5), 6, 1, "Roll Dice")
[Link]()
quitButton = Button(win, Point(5,1), 2, 1, "Quit")

Python Programming, 1/e 104


The Main Program
# Event loop
pt = [Link]()
while not [Link](pt):
if [Link](pt):
value1 = randrange(1,7)
[Link](value1)
value2 = randrange(1,7)
[Link](value2)
[Link]()
pt = [Link]()

# close up shop
[Link]()

main()

Python Programming, 1/e 105


The Main Program
 The visual interface is built by creating
the two DieViews and two Buttons.
 The roll button is initially active, but
the quit button is deactivated. This
forces the user to roll the dice at least
once.
 The event loop is a sentinel loop that
gets mouse clicks and processes them
until the user clicks on the quit button.

Python Programming, 1/e 106


The Main Program
 The if within the loop ensures that
the dice are rolled only when the
user clicks the roll button.
 Clicking a point that is not inside
any button causes the loop to
iterate without doing anything.

Python Programming, 1/e 107

You might also like