Presentation is loading. Please wait.

Presentation is loading. Please wait.

Python Programming: An Introduction to Computer Science

Similar presentations


Presentation on theme: "Python Programming: An Introduction to Computer Science"— Presentation transcript:

1 Python Programming: An Introduction to Computer Science
Chapter 1 Computers and Programs Python Programming, 2/e Python Programming, 2/e

2 Objectives To understand the respective roles of hardware and software in a computing system. To learn what computer scientists study and the techniques that they use. To understand the basic design of a modern computer. Python Programming, 2/e

3 Objectives (cont.) To understand the form and function of computer programming languages. To begin using the Python programming language. To learn about chaotic models and their implications for computing. Python Programming, 2/e

4 The Universal Machine A modern computer can be defined as “a machine that stores and manipulates information under the control of a changeable program.” Two key elements: Computers are devices for manipulating information. Computers operate under the control of a changeable program. Python Programming, 2/e

5 The Universal Machine What is a computer program?
A detailed, step-by-step set of instructions telling a computer what to do. If we change the program, the computer performs a different set of actions or a different task. The machine stays the same, but the program changes! Python Programming, 2/e

6 The Universal Machine Programs are executed, or carried out.
All computers have the same power, with suitable programming, i.e. each computer can do the things any other computer can do. Python Programming, 2/e

7 Program Power Software (programs) rule the hardware (the physical machine). The process of creating this software is called programming. Why learn to program? Fundamental part of computer science Having an understanding of programming helps you have an understanding of the strengths and limitations of computers. Python Programming, 2/e

8 Program Power Helps you become a more intelligent user of computers
It can be fun! Form of expression Helps the development of problem solving skills, especially in analyzing complex systems by reducing them to interactions between simpler systems. Programmers are in great demand! Python Programming, 2/e

9 What is Computer Science?
It is not the study of computers! “Computers are to computer science what telescopes are to astronomy.” – E. Dijkstra The question becomes, “What processes can be described?” This question is really, “What can be computed?” Python Programming, 2/e

10 What is Computer Science?
Design One way to show a particular problem can be solved is to actually design a solution. This is done by developing an algorithm, a step-by-step process for achieving the desired result. One problem – it can only answer in the positive. You can’t prove a negative! Python Programming, 2/e

11 What is Computer Science?
Analysis Analysis is the process of examining algorithms and problems mathematically. Some seemingly simple problems are not solvable by any algorithm. These problems are said to be unsolvable. Problems can be intractable if they would take too long or take too much memory to be of practical value. Python Programming, 2/e

12 What is Computer Science?
Experimentation Some problems are too complex for analysis. Implement a system and then study its behavior. Python Programming, 2/e

13 Hardware Basics The central processing unit (CPU) is the “brain” of a computer. The CPU carries out all the basic operations on the data. Examples: simple arithmetic operations, testing to see if two numbers are equal. Python Programming, 2/e

14 Hardware Basics Memory stores programs and data.
CPU can only directly access information stored in main memory (RAM or Random Access Memory). Main memory is fast, but volatile, i.e. when the power is interrupted, the contents of memory are lost. Secondary memory provides more permanent storage: magnetic (hard drive, floppy), optical (CD, DVD) Python Programming, 2/e

15 Hardware Basics Input devices Output devices
Information is passed to the computer through keyboards, mice, etc. Output devices Processed information is presented to the user through the monitor, printer, etc. Python Programming, 2/e

16 Hardware Basics Fetch-Execute Cycle
First instruction retrieved from memory Decode the instruction to see what it represents Appropriate action carried out. Next instruction fetched, decoded, and executed. Lather, rinse, repeat! Python Programming, 2/e

17 Programming Languages
Natural language has ambiguity and imprecision problems when used to describe complex algorithms. Programs expressed in an unambiguous , precise way using programming languages. Every structure in programming language has a precise form, called its syntax Every structure in programming language has a precise meaning, called its semantics. Python Programming, 2/e

18 Programming Languages
Programming language like a code for writing the instructions the computer will follow. Programmers will often refer to their program as computer code. Process of writing an algorithm in a programming language often called coding. Python Programming, 2/e

19 Programming Languages
High-level computer languages Designed to be used and understood by humans Low-level language Computer hardware can only understand a very low level language known as machine language Python Programming, 2/e

20 Programming Languages
Add two numbers: Load the number from memory location 2001 into the CPU Load the number from memory location 2002 into the CPU Add the two numbers in the CPU Store the result into location 2003 In reality, these low-level instructions are represented in binary (1’s and 0’s) Python Programming, 2/e

21 Programming Languages
High-level language c = a + b This needs to be translated into machine language that the computer can execute. Compilers convert programs written in a high-level language into the machine language of some computer. Python Programming, 2/e

22 Programming Languages
Interpreters simulate a computer that understands a high-level language. The source program is not translated into machine language all at once. An interpreter analyzes and executes the source code instruction by instruction. Python Programming, 2/e

23 Programming Languages
Compiling vs. Interpreting Once program is compiled, it can be executed over and over without the source code or compiler. If it is interpreted, the source code and interpreter are needed each time the program runs Compiled programs generally run faster since the translation of the source code happens only once. Python Programming, 2/e

24 Programming Languages
Interpreted languages are part of a more flexible programming environment since they can be developed and run interactively Interpreted programs are more portable, meaning the executable code produced from a compiler for a Pentium won’t run on a Mac, without recompiling. If a suitable interpreter already exists, the interpreted code can be run with no modifications. Python Programming, 2/e

25 The Magic of Python When you start Python, you will see something like: Python (r312:79149, Mar , 00:41:52) [MSC v bit (Intel)] on win32 Type "copyright", "credits" or "license()" for more information. >>> Python Programming, 2/e

26 The Magic of Python The “>>>” is a Python prompt indicating that Python is ready for us to give it a command. These commands are called statements. >>> print("Hello, world“) Hello, world >>> print(2+3) 5 >>> print("2+3=", 2+3) 2+3= 5 >>> Python Programming, 2/e

27 The Magic of Python Usually we want to execute several statements together that solve a common problem. One way to do this is to use a function. >>> def hello(): print("Hello") print("Computers are Fun") >>> Python Programming, 2/e

28 The Magic of Python >>> def hello(): print("Hello") print("Computers are Fun") >>> The first line tells Python we are defining a new function called hello. The following lines are indented to show that they are part of the hello function. The blank line (hit enter twice) lets Python know the definition is finished. Python Programming, 2/e

29 The Magic of Python >>> def hello(): print("Hello") print("Computers are Fun") >>> Notice that nothing has happened yet! We’ve defined the function, but we haven’t told Python to perform the function! A function is invoked by typing its name. >>> hello() Hello Computers are Fun >>> Python Programming, 2/e

30 The Magic of Python What’s the deal with the ()’s?
Commands can have changeable parts called parameters that are placed between the ()’s. >>> def greet(person): print("Hello",person) print ("How are you?") >>> Python Programming, 2/e

31 The Magic of Python >>> greet("Terry") Hello Terry How are you? >>> greet("Paula") Hello Paula How are you? >>> When we use parameters, we can customize the output of our function. Python Programming, 2/e

32 The Magic of Python When we exit the Python prompt, the functions we’ve defined cease to exist! Programs are usually composed of functions, modules, or scripts that are saved on disk so that they can be used again and again. A module file is a text file created in text editing software (saved as “plain text”) that contains function definitions. A programming environment is designed to help programmers write programs and usually includes automatic indenting, highlighting, etc. Python Programming, 2/e

33 The Magic of Python # File: chaos.py # A simple program illustrating chaotic behavior def main(): print("This program illustrates a chaotic function") x = eval(input("Enter a number between 0 and 1: ")) for i in range(10): x = 3.9 * x * (1 - x) print(x) main() We’ll use filename.py when we save our work to indicate it’s a Python program. In this code we’re defining a new function called main. The main() at the end tells Python to run the code. Python Programming, 2/e

34 The Magic of Python >>>
This program illustrates a chaotic function Enter a number between 0 and 1: .5 0.975 Python Programming, 2/e

35 Inside a Python Program
# File: chaos.py # A simple program illustrating chaotic behavior Lines that start with # are called comments Intended for human readers and ignored by Python Python skips text from # to end of line Python Programming, 2/e

36 Inside a Python Program
def main(): Beginning of the definition of a function called main Since our program has only this one module, it could have been written without the main function. The use of main is customary, however. Python Programming, 2/e

37 Inside a Python Program
print("This program illustrates a chaotic function") This line causes Python to print a message introducing the program. Python Programming, 2/e

38 Inside a Python Program
x = eval(input("Enter a number between 0 and 1: ")) x is an example of a variable A variable is used to assign a name to a value so that we can refer to it later. The quoted information is displayed, and the number typed in response is stored in x. Python Programming, 2/e

39 Inside a Python Program
for i in range(10): For is a loop construct A loop tells Python to repeat the same thing over and over. In this example, the following code will be repeated 10 times. Python Programming, 2/e

40 Inside a Python Program
x = 3.9 * x * (1 - x) print(x) These lines are the body of the loop. The body of the loop is what gets repeated each time through the loop. The body of the loop is identified through indentation. The effect of the loop is the same as repeating this two lines 10 times! Python Programming, 2/e

41 Inside a Python Program
for i in range(10): x = 3.9 * x * (1 - x) print(x) These are equivalent! x = 3.9 * x * (1 - x) print(x) Python Programming, 2/e

42 Inside a Python Program
x = 3.9 * x * (1 - x) This is called an assignment statement The part on the right-hand side (RHS) of the “=“ is a mathematical expression. * is used to indicate multiplication Once the value on the RHS is computed, it is stored back into (assigned) into x Python Programming, 2/e

43 Inside a Python Program
main() This last line tells Python to execute the code in the function main Python Programming, 2/e

44 Chaos and Computers The chaos.py program:
def main(): print("This program illustrates a chaotic function") x = eval(input("Enter a number between 0 and 1: ")) for i in range(10): x = 3.9 * x * (1 - x) print(x) main() For any given input, returns 10 seemingly random numbers between 0 and 1 It appears that the value of x is chaotic Python Programming, 2/e

45 Chaos and Computers The function computed by program has the general form where k is 3.9 This type of function is known as a logistic function. Models certain kinds of unstable electronic circuits. Very small differences in initial value can have large differences in the output. Python Programming, 2/e

46 Chaos and Computers Input: 0.25 0.73125 0.76644140625 0.698135010439
Input: 0.26 Python Programming, 2/e

47 Python Programming: An Introduction to Computer Science
Chapter 2 Python Programming, 2/e

48 Objectives To be able to understand and write Python statements to output information to the screen, assign values to variables, get numeric information entered from the keyboard, and perform a counted loop Python Programming, 2/e

49 The Software Development Process
The process of creating a program is often broken down into stages according to the information that is produced in each phase. Python Programming, 2/e

50 The Software Development Process
Analyze the Problem Figure out exactly the problem to be solved. Try to understand it as much as possible. Python Programming, 2/e

51 The Software Development Process
Determine Specifications Describe exactly what your program will do. Don’t worry about how the program will work, but what it will do. Includes describing the inputs, outputs, and how they relate to one another. Python Programming, 2/e

52 The Software Development Process
Create a Design Formulate the overall structure of the program. This is where the how of the program gets worked out. You choose or develop your own algorithm that meets the specifications. Python Programming, 2/e

53 The Software Development Process
Implement the Design Translate the design into a computer language. In this course we will use Python. Python Programming, 2/e

54 The Software Development Process
Test/Debug the Program Try out your program to see if it worked. If there are any errors (bugs), they need to be located and fixed. This process is called debugging. Your goal is to find errors, so try everything that might “break” your program! Python Programming, 2/e

55 The Software Development Process
Maintain the Program Continue developing the program in response to the needs of your users. In the real world, most programs are never completely finished – they evolve over time. Python Programming, 2/e

56 Example Program: Temperature Converter
Analysis – the temperature is given in Celsius, user wants it expressed in degrees Fahrenheit. Specification Input – temperature in Celsius Output – temperature in Fahrenheit Output = 9/5(input) + 32 Python Programming, 2/e

57 Example Program: Temperature Converter
Design Input, Process, Output (IPO) Prompt the user for input (Celsius temperature) Process it to convert it to Fahrenheit using F = 9/5(C) + 32 Output the result by displaying it on the screen Python Programming, 2/e

58 Example Program: Temperature Converter
Before we start coding, let’s write a rough draft of the program in pseudocode Pseudocode is precise English that describes what a program does, step by step. Using pseudocode, we can concentrate on the algorithm rather than the programming language. Python Programming, 2/e

59 Example Program: Temperature Converter
Pseudocode: Input the temperature in degrees Celsius (call it celsius) Calculate fahrenheit as (9/5)*celsius+32 Output fahrenheit Now we need to convert this to Python! Python Programming, 2/e

60 Example Program: Temperature Converter
#convert.py # A program to convert Celsius temps to Fahrenheit # by: Susan Computewell def main(): celsius = eval(input("What is the Celsius temperature? ")) fahrenheit = (9/5) * celsius + 32 print("The temperature is ",fahrenheit," degrees Fahrenheit.") main() Python Programming, 2/e Python Programming, 1/e

61 Example Program: Temperature Converter
Once we write a program, we should test it! >>> What is the Celsius temperature? 0 The temperature is degrees Fahrenheit. >>> main() What is the Celsius temperature? 100 The temperature is degrees Fahrenheit. What is the Celsius temperature? -40 The temperature is degrees Fahrenheit. Python Programming, 2/e

62 Elements of Programs Names
Names are given to variables (celsius, fahrenheit), modules (main, convert), etc. These names are called identifiers Every identifier must begin with a letter or underscore (“_”), followed by any sequence of letters, digits, or underscores. Identifiers are case sensitive. Python Programming, 2/e

63 Elements of Programs These are all different, valid names X Celsius
Spam spam spAm Spam_and_Eggs Spam_And_Eggs Python Programming, 2/e

64 Elements of Programs Some identifiers are part of Python itself. These identifiers are known as reserved words. This means they are not available for you to use as a name for a variable, etc. in your program. and, del, for, is, raise, assert, elif, in, print, etc. For a complete list, see table 2.1 Python Programming, 2/e

65 Elements of Programs Expressions
The fragments of code that produce or calculate new data values are called expressions. Literals are used to represent a specific value, e.g. 3.9, 1, 1.0 Simple identifiers can also be expressions. Python Programming, 2/e

66 Elements of Programs >>> x = 5 >>> x 5 >>> print(x) >>> print(spam) Traceback (most recent call last): File "<pyshell#15>", line 1, in -toplevel- print spam NameError: name 'spam' is not defined >>> NameError is the error when you try to use a variable without a value assigned to it. Python Programming, 2/e

67 Elements of Programs Simpler expressions can be combined using operators. +, -, *, /, ** Spaces are irrelevant within an expression. The normal mathematical precedence applies. ((x1 – x2) / 2*n) + (spam / k**3) Python Programming, 2/e

68 Elements of Programs Output Statements
A print statement can print any number of expressions. Successive print statements will display on separate lines. A bare print will print a blank line. Python Programming, 2/e

69 Elements of Programs print(3+4) print(3, 4, 3+4) print()
print(3, 4, end=" "), print(3 + 4) print("The answer is", 3+4) 7 3 4 7 The answer is 7 Python Programming, 2/e

70 Assignment Statements
Simple Assignment <variable> = <expr> variable is an identifier, expr is an expression The expression on the RHS is evaluated to produce a value which is then associated with the variable named on the LHS. Python Programming, 2/e

71 Assignment Statements
x = 3.9 * x * (1-x) fahrenheit = 9/5 * celsius + 32 x = 5 Python Programming, 2/e

72 Assignment Statements
Variables can be reassigned as many times as you want! >>> myVar = 0 >>> myVar >>> myVar = 7 7 >>> myVar = myVar + 1 8 >>> Python Programming, 2/e

73 Assignment Statements
Variables are like a box we can put values in. When a variable changes, the old value is erased and a new one is written in. Python Programming, 2/e

74 Assignment Statements
Technically, this model of assignment is simplistic for Python. Python doesn't overwrite these memory locations (boxes). Assigning a variable is more like putting a “sticky note” on a value and saying, “this is x”. Python Programming, 2/e

75 Assigning Input The purpose of an input statement is to get input from the user and store it into a variable. <variable> = eval(input(<prompt>)) Python Programming, 2/e

76 Assigning Input First the prompt is printed
The input part waits for the user to enter a value and press <enter> The expression that was entered is evaluated to turn it from a string of characters into a Python value (a number). The value is assigned to the variable. Python Programming, 2/e

77 Simultaneous Assignment
Several values can be calculated at the same time <var>, <var>, … = <expr>, <expr>, … Evaluate the expressions in the RHS and assign them to the variables on the LHS Python Programming, 2/e

78 Simultaneous Assignment
sum, diff = x+y, x-y How could you use this to swap the values for x and y? Why doesn’t this work? x = y y = x We could use a temporary variable… Python Programming, 2/e

79 Simultaneous Assignment
We can swap the values of two variables quite easily in Python! x, y = y, x >>> x = 3 >>> y = 4 >>> print x, y 3 4 >>> x, y = y, x 4 3 Python Programming, 2/e

80 Simultaneous Assignment
We can use this same idea to input multiple variables from a single input statement! Use commas to separate the inputs def spamneggs(): spam, eggs = eval(input("Enter # of slices of spam followed by # of eggs: ")) print ("You ordered", eggs, "eggs and", spam, "slices of spam. Yum!“) >>> spamneggs() Enter the number of slices of spam followed by the number of eggs: 3, 2 You ordered 2 eggs and 3 slices of spam. Yum! >>> Python Programming, 2/e

81 Definite Loops A definite loop executes a definite number of times, i.e., at the time Python starts the loop it knows exactly how many iterations to do. for <var> in <sequence>: <body> The beginning and end of the body are indicated by indentation. Python Programming, 2/e

82 Definite Loops for <var> in <sequence>: <body>
The variable after the for is called the loop index. It takes on each successive value in sequence. Python Programming, 2/e

83 Definite Loops >>> for i in [0,1,2,3]: print (i) 1 2 3
1 2 3 >>> for odd in [1, 3, 5, 7]: print(odd*odd) 9 25 49 >>> Python Programming, 2/e

84 Definite Loops In chaos.py, what did range(10) do? >>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] range is a built-in Python function that generates a sequence of numbers, starting with 0. list is a built-in Python function that turns the sequence into an explicit list The body of the loop executes 10 times. Python Programming, 2/e

85 Definite Loops for loops alter the flow of program execution, so they are referred to as control structures. Python Programming, 2/e

86 Example Program: Future Value
Analysis Money deposited in a bank account earns interest. How much will the account be worth 10 years from now? Inputs: principal, interest rate Output: value of the investment in 10 years Python Programming, 2/e

87 Example Program: Future Value
Specification User enters the initial amount to invest, the principal User enters an annual percentage rate, the interest The specifications can be represented like this … Python Programming, 2/e

88 Example Program: Future Value
Inputs principal The amount of money being invested, in dollars apr The annual percentage rate expressed as a decimal number. Output The value of the investment 10 years in the future Relatonship Value after one year is given by principal * (1 + apr). This needs to be done 10 times. Python Programming, 2/e

89 Example Program: Future Value
Design Print an introduction Input the amount of the principal (principal) Input the annual percentage rate (apr) Repeat 10 times: principal = principal * (1 + apr) Output the value of principal Python Programming, 2/e

90 Example Program: Future Value
Implementation Each line translates to one line of Python (in this case) Print an introduction print ("This program calculates the future") print ("value of a 10-year investment.") Input the amount of the principal principal = eval(input("Enter the initial principal: ")) Python Programming, 2/e

91 Example Program: Future Value
Input the annual percentage rate apr = eval(input("Enter the annual interest rate: ")) Repeat 10 times: for i in range(10): Calculate principal = principal * (1 + apr) principal = principal * (1 + apr) Output the value of the principal at the end of 10 years print ("The value in 10 years is:", principal) Python Programming, 2/e

92 Example Program: Future Value
# futval.py # A program to compute the value of an investment # carried 10 years into the future def main(): print("This program calculates the future value of a 10-year investment.") principal = eval(input("Enter the initial principal: ")) apr = eval(input("Enter the annual interest rate: ")) for i in range(10): principal = principal * (1 + apr) print ("The value in 10 years is:", principal) main() Python Programming, 2/e

93 Example Program: Future Value
>>> main() This program calculates the future value of a 10-year investment. Enter the initial principal: 100 Enter the annual interest rate: .03 The value in 10 years is: Enter the annual interest rate: .10 The value in 10 years is: Python Programming, 2/e

94 Python Programming: An Introduction to Computer Science
Chapter 3 Computing with Numbers Python Programming, 2/e

95 Objectives To understand the concept of data types.
To be familiar with the basic numeric data types in Python. To understand the fundamental principles of how numbers are represented on a computer. Python Programming, 2/e

96 Objectives (cont.) To be able to use the Python math library.
To understand the accumulator program pattern. To be able to read and write programs that process numerical data. Python Programming, 2/e

97 Numeric Data Types The information that is stored and manipulated bu computers programs is referred to as data. There are two different kinds of numbers! (5, 4, 3, 6) are whole numbers – they don’t have a fractional part (.25, .10, .05, .01) are decimal fractions Python Programming, 2/e

98 Numeric Data Types Inside the computer, whole numbers and decimal fractions are represented quite differently! We say that decimal fractions and whole numbers are two different data types. The data type of an object determines what values it can have and what operations can be performed on it. Python Programming, 2/e

99 Numeric Data Types Whole numbers are represented using the integer (int for short) data type. These values can be positive or negative whole numbers. Python Programming, 2/e

100 Numeric Data Types Numbers that can have fractional parts are represented as floating point (or float) values. How can we tell which is which? A numeric literal without a decimal point produces an int value A literal that has a decimal point is represented by a float (even if the fractional part is 0) Python Programming, 2/e

101 Numeric Data Types Python has a special function to tell us the data type of any value. >>> type(3) <class 'int'> >>> type(3.1) <class 'float'> >>> type(3.0) >>> myInt = 32 >>> type(myInt) >>> Python Programming, 2/e

102 Numeric Data Types Why do we need two number types?
Values that represent counts can’t be fractional (you can’t have 3 ½ quarters) Most mathematical algorithms are very efficient with integers The float type stores only an approximation to the real number being represented! Since floats aren’t exact, use an int whenever possible! Python Programming, 2/e

103 Numeric Data Types Operations on ints produce ints, operations on floats produce floats (except for /). >>> 7.0 >>> 3+4 7 >>> 3.0*4.0 12.0 >>> 3*4 12 >>> 10.0/3.0 >>> 10/3 >>> 10 // 3 3 >>> 10.0 // 3.0 3.0 Python Programming, 2/e

104 Numeric Data Types Integer division produces a whole number.
That’s why 10//3 = 3! Think of it as ‘gozinta’, where 10//3 = 3 since 3 gozinta (goes into) 10 3 times (with a remainder of 1) 10%3 = 1 is the remainder of the integer division of 10 by 3. a = (a/b)(b) + (a%b) Python Programming, 2/e

105 Using the Math Library Besides (+, -, *, /, //, **, %, abs), we have lots of other math functions available in a math library. A library is a module with some useful definitions/functions. Python Programming, 2/e

106 Using the Math Library Let’s write a program to compute the roots of a quadratic equation! The only part of this we don’t know how to do is find a square root… but it’s in the math library! Python Programming, 2/e

107 Using the Math Library To use a library, we need to make sure this line is in our program: import math Importing a library makes whatever functions are defined within it available to the program. Python Programming, 2/e

108 Using the Math Library To access the sqrt library routine, we need to access it as math.sqrt(x). Using this dot notation tells Python to use the sqrt function found in the math library module. To calculate the root, you can do discRoot = math.sqrt(b*b – 4*a*c) Python Programming, 2/e

109 Using the Math Library Python Programming, 2/e # quadratic.py
# A program that computes the real roots of a quadratic equation. # Illustrates use of the math library. # Note: This program crashes if the equation has no real roots. import math # Makes the math library available. def main(): print("This program finds the real solutions to a quadratic") print() a, b, c = eval(input("Please enter the coefficients (a, b, c): ")) discRoot = math.sqrt(b * b - 4 * a * c) root1 = (-b + discRoot) / (2 * a) root2 = (-b - discRoot) / (2 * a) print("The solutions are:", root1, root2 ) main() Python Programming, 2/e

110 Using the Math Library What do you suppose this means?
This program finds the real solutions to a quadratic Please enter the coefficients (a, b, c): 3, 4, -1 The solutions are: What do you suppose this means? Please enter the coefficients (a, b, c): 1, 2, 3 Traceback (most recent call last): File "<pyshell#26>", line 1, in -toplevel- main() File "C:\Documents and Settings\Terry\My Documents\Teaching\W04\CS 120\Textbook\code\chapter3\quadratic.py", line 14, in main discRoot = math.sqrt(b * b - 4 * a * c) ValueError: math domain error >>> Python Programming, 2/e

111 Math Library If a = 1, b = 2, c = 3, then we are trying to take the square root of a negative number! Using the sqrt function is more efficient than using **. How could you use ** to calculate a square root? Python Programming, 2/e

112 Accumulating Results: Factorial
Say you are waiting in a line with five other people. How many ways are there to arrange the six people? is the factorial of 6 (abbreviated 6!) Factorial is defined as: n! = n(n-1)(n-2)…(1) So, 6! = 6*5*4*3*2*1 = 720 Python Programming, 2/e

113 Accumulating Results: Factorial
How we could we write a program to do this? Input number to take factorial of, n Compute factorial of n, fact Output fact Python Programming, 2/e

114 Accumulating Results: Factorial
How did we calculate 6!? 6*5 = 30 Take that 30, and 30 * 4 = 120 Take that 120, and 120 * 3 = 360 Take that 360, and 360 * 2 = 720 Take that 720, and 720 * 1 = 720 Python Programming, 2/e

115 Accumulating Results: Factorial
What’s really going on? We’re doing repeated multiplications, and we’re keeping track of the running product. This algorithm is known as an accumulator, because we’re building up or accumulating the answer in a variable, known as the accumulator variable. Python Programming, 2/e

116 Accumulating Results: Factorial
The general form of an accumulator algorithm looks like this: Initialize the accumulator variable Loop until final result is reached update the value of accumulator variable Python Programming, 2/e

117 Accumulating Results: Factorial
It looks like we’ll need a loop! fact = 1 for factor in [6, 5, 4, 3, 2, 1]: fact = fact * factor Let’s trace through it to verify that this works! Python Programming, 2/e

118 Accumulating Results: Factorial
Why did we need to initialize fact to 1? There are a couple reasons… Each time through the loop, the previous value of fact is used to calculate the next value of fact. By doing the initialization, you know fact will have a value the first time through. If you use fact without assigning it a value, what does Python do? Python Programming, 2/e

119 Accumulating Results: Factorial
Since multiplication is associative and commutative, we can rewrite our program as: fact = 1 for factor in [2, 3, 4, 5, 6]: fact = fact * factor Great! But what if we want to find the factorial of some other number?? Python Programming, 2/e

120 Accumulating Results: Factorial
What does range(n) return? 0, 1, 2, 3, …, n-1 range has another optional parameter! range(start, n) returns start, start + 1, …, n-1 But wait! There’s more! range(start, n, step) start, start+step, …, n-1 list(<sequence>) to make a list Python Programming, 2/e

121 Accumulating Results: Factorial
Let’s try some examples! >>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(range(5,10)) [5, 6, 7, 8, 9] >>> list(range(5,10,2)) [5, 7, 9] Python Programming, 2/e

122 Accumulating Results: Factorial
Using this souped-up range statement, we can do the range for our loop a couple different ways. We can count up from 2 to n: range(2, n+1) (Why did we have to use n+1?) We can count down from n to 2: range(n, 1, -1) Python Programming, 2/e

123 Accumulating Results: Factorial
Our completed factorial program: # factorial.py # Program to compute the factorial of a number # Illustrates for loop with an accumulator def main(): n = eval(input("Please enter a whole number: ")) fact = 1 for factor in range(n,1,-1): fact = fact * factor print("The factorial of", n, "is", fact) main() Python Programming, 2/e

124 The Limits of Int What is 100!? Wow! That’s a pretty big number!
>>> main() Please enter a whole number: 100 The factorial of 100 is Wow! That’s a pretty big number! Python Programming, 2/e

125 The Limits of Int Newer versions of Python can handle it, but…
Python (#0, Apr , 10:51:12) [MSC 32 bit (Intel)] on win32 Copyright Stichting Mathematisch Centrum, Amsterdam >>> import fact >>> fact.main() Please enter a whole number: 13 13 12 11 10 9 8 7 6 5 4 Traceback (innermost last): File "<pyshell#1>", line 1, in ? fact.main() File "C:\PROGRA~1\PYTHON~1.2\fact.py", line 5, in main fact=fact*factor OverflowError: integer multiplication Python Programming, 2/e

126 The Limits of Int What’s going on?
While there are an infinite number of integers, there is a finite range of ints that can be represented. This range depends on the number of bits a particular CPU uses to represent an integer value. Typical PCs use 32 bits. Python Programming, 2/e

127 The Limits of Int Typical PCs use 32 bits
That means there are 232 possible values, centered at 0. This range then is –231 to We need to subtract one from the top end to account for 0. But our 100! is much larger than this. How does it work? Python Programming, 2/e

128 Handling Large Numbers
Does switching to float data types get us around the limitations of ints? If we initialize the accumulator to 1.0, we get >>> main() Please enter a whole number: 15 The factorial of 15 is e+012 We no longer get an exact answer! Python Programming, 2/e

129 Handling Large Numbers: Long Int
Very large and very small numbers are expressed in scientific or exponential notation. e+012 means * 1012 Here the decimal needs to be moved right 12 decimal places to get the original number, but there are only 9 digits, so 3 digits of precision have been lost. Python Programming, 2/e

130 Handling Large Numbers
Floats are approximations Floats allow us to represent a larger range of values, but with lower precision. Python has a solution, expanding ints! Python Ints are not a fixed size and expand to handle whatever value it holds. Python Programming, 2/e

131 Handling Large Numbers
Newer versions of Python automatically convert your ints to expanded form when they grow so large as to overflow. We get indefinitely large values (e.g. 100!) at the cost of speed and memory Python Programming, 2/e

132 Type Conversions We know that combining an int with an int produces an int, and combining a float with a float produces a float. What happens when you mix an int and float in an expression? x = What do you think should happen? Python Programming, 2/e

133 Type Conversions For Python to evaluate this expression, it must either convert 5.0 to 5 and do an integer addition, or convert 2 to 2.0 and do a floating point addition. Converting a float to an int will lose information Ints can be converted to floats by adding “.0” Python Programming, 2/e

134 Type Conversion In mixed-typed expressions Python will convert ints to floats. Sometimes we want to control the type conversion. This is called explicit typing. Python Programming, 2/e

135 Type Conversions >>> float(22//5) 4.0 >>> int(4.5) 4
3 >>> round(3.9) >>> round(3) Python Programming, 2/e

136 Python Programming: An Introduction to Computer Science
Chapter 4 Objects and Graphics Python Programming, 2/e 136 Python Programming, 1/e

137 Objectives To understand the concept of objects and how they can be used to simplify programs. To be familiar with the various objects available in the graphics library. To be able to create objects in programs and call appropriate methods to perform graphical computations. Python Programming, 2/e 137 Python Programming, 1/e

138 Objectives (cont.) To understand the fundamental concepts of computer graphics, especially the role of coordinate systems and coordinate transformations. To understand how to work with both mouse and text-based input in a graphical programming context. Python Programming, 2/e 138 Python Programming, 1/e

139 Objectives (cont.) To be able to write simple interactive graphics programs using the graphics library. Python Programming, 2/e 139 Python Programming, 1/e

140 Overview Each data type can represent a certain set of values, and each had a set of associated operations. The traditional programming view is that data is passive – it’s manipulated and combined with active operations. Python Programming, 2/e 140 Python Programming, 1/e

141 Overview Modern computer programs are built using an object-oriented approach. Most applications you’re familiar with have Graphical User Interfaces (GUI) that provide windows, icons, buttons and menus. There’s a graphics library (graphics.py) written specifically to go with this book. It’s based on Tkinter. Python Programming, 2/e 141 Python Programming, 1/e

142 The Object of Objects Basic idea – view a complex system as the interaction of simpler objects. An object is a sort of active data type that combines data and operations. Objects know stuff (contain data) and they can do stuff (have operations). Objects interact by sending each other messages. Python Programming, 2/e 142 Python Programming, 1/e

143 The Object of Objects Suppose we want to develop a data processing system for a college or university. We must keep records on students who attend the school. Each student will be represented as an object. Python Programming, 2/e 143 Python Programming, 1/e

144 The Object of Objects The student object would contain data like: Name
ID number Courses taken Campus Address Home Address GPA Etc. Python Programming, 2/e 144 Python Programming, 1/e

145 The Object of Objects The student object should also respond to requests. We may want to send out a campus-wide mailing, so we’d need a campus address for each student. We could send the printCampusAddress to each student object. When the student object receives the message, it prints its own address. Python Programming, 2/e 145 Python Programming, 1/e

146 Object of Objects Instructor Student roster Prerequisite courses
Objects may refer to other objects. Each course might be represented by an object: Instructor Student roster Prerequisite courses When and where the class meets Python Programming, 2/e 146 Python Programming, 1/e

147 Object of Objects addStudent delStudent changeRoom Etc.
Sample Operation addStudent delStudent changeRoom Etc. Python Programming, 2/e 147 Python Programming, 1/e

148 Simple Graphics Programming
This chapter uses the graphics.py library supplied with the supplemental materials. Two location choices In Python’s Lib directory with other libraries In the same folder as your graphics program Python Programming, 2/e 148 Python Programming, 1/e

149 Simple Graphics Programming
Since this is a library, we need to import the graphics commands >>> import graphics A graphics window is a place on the screen where the graphics will appear. >>> win = graphics.GraphWin() This command creates a new window titled “Graphics Window.” Python Programming, 2/e 149 Python Programming, 1/e

150 Simple Graphics Programming
GraphWin is an object assigned to the variable win. We can manipulate the window object through this variable, similar to manipulating files through file variables. Windows can be closed/destroyed by issuing the command >>> win.close() Python Programming, 2/e 150 Python Programming, 1/e

151 Simple Graphics Programming
It’s tedious to use the graphics. notation to access the graphics library routines. from graphics import * The “from” statement allows you to load specific functions from a library module. “*” will load all the functions, or you can list specific ones. Python Programming, 2/e 151 Python Programming, 1/e

152 Simple Graphics Programming
Doing the import this way eliminates the need to preface graphics commands with graphics. >>> from graphics import * >>> win = GraphWin() Python Programming, 2/e 152 Python Programming, 1/e

153 Simple Graphics Programming
A graphics window is a collection of points called pixels (picture elements). The default GraphWin is 200 pixels tall by 200 pixels wide (40,000 pixels total). One way to get pictures into the window is one pixel at a time, which would be tedious. The graphics routine has a number of predefined routines to draw geometric shapes. Python Programming, 2/e 153 Python Programming, 1/e Python Programming, 1/e 153

154 Simple Graphics Programming
The simplest object is the Point. Like points in geometry, point locations are represented with a coordinate system (x, y), where x is the horizontal location of the point and y is the vertical location. The origin (0,0) in a graphics window is the upper left corner. X values increase from left to right, y values from top to bottom. Lower right corner is (199, 199) Python Programming, 2/e 154 Python Programming, 1/e

155 Simple Graphics Programming
>>> p = Point(50, 60) >>> p.getX() 50 >>> p.getY() 60 >>> win = GraphWin() >>> p.draw(win) >>> p2 = Point(140, 100) >>> p2.draw(win) Python Programming, 2/e 155 Python Programming, 1/e

156 Simple Graphics Programming
>>> ### Open a graphics window >>> win = GraphWin('Shapes') >>> ### Draw a red circle centered at point (100, 100) with radius 30 >>> center = Point(100, 100) >>> circ = Circle(center, 30) >>> circ.setFill('red') >>> circ.draw(win) >>> ### Put a textual label in the center of the circle >>> label = Text(center, "Red Circle") >>> label.draw(win) >>> ### Draw a square using a Rectangle object >>> rect = Rectangle(Point(30, 30), Point(70, 70)) >>> rect.draw(win) >>> ### Draw a line segment using a Line object >>> line = Line(Point(20, 30), Point(180, 165)) >>> line.draw(win) >>> ### Draw an oval using the Oval object >>> oval = Oval(Point(20, 150), Point(180, 199)) >>> oval.draw(win) Python Programming, 2/e 156 Python Programming, 1/e

157 Using Graphical Objects
Computation is preformed by asking an object to carry out one of its operations. In the previous example we manipulated GraphWin, Point, Circle, Oval, Line, Text and Rectangle. These are examples of classes. Python Programming, 2/e 157 Python Programming, 1/e

158 Using Graphical Objects
Each object is an instance of some class, and the class describes the properties of the instance. If we say that Augie is a dog, we are actually saying that Augie is a specific individual in the larger class of all dogs. Augie is an instance of the dog class. Python Programming, 2/e 158 Python Programming, 1/e

159 Using Graphical Objects
To create a new instance of a class, we use a special operation called a constructor. <class-name>(<param1>, <param2>, …) <class-name> is the name of the class we want to create a new instance of, e.g. Circle or Point. The parameters are required to initialize the object. For example, Point requires two numeric values. Python Programming, 2/e 159 Python Programming, 1/e

160 Using Graphical Objects
p = Point(50, 60) The constructor for the Point class requires to parameters, the x and y coordinates for the point. These values are stored as instance variables inside of the object. Python Programming, 2/e 160 Python Programming, 1/e

161 Using Graphical Objects
Only the most relevant instance variables are shown (others include the color, window they belong to, etc.) Python Programming, 2/e 161 Python Programming, 1/e

162 Using Graphical Objects
To perform an operation on an object, we send the object a message. The set of messages an object responds to are called the methods of the object. Methods are like functions that live inside the object. Methods are invoked using dot-notation: <object>.<method-name>(<param1>, <param2>, …) Python Programming, 2/e 162 Python Programming, 1/e

163 Using Graphical Objects
p.getX() and p.getY() returns the x and y values of the point. Routines like these are referred to as accessors because they allow us to access information from the instance variables of the object. Python Programming, 2/e 163 Python Programming, 1/e

164 Using Graphical Objects
Other methods change the state of the object by changing the values of the object’s instance variables. move(dx, dy) moves the object dx units in the x direction and dy in the y direction. Move erases the old image and draws it in its new position. Methods that change the state of an object are called mutators. Python Programming, 2/e 164 Python Programming, 1/e

165 Using Graphical Objects
>>> circ = Circle(Point(100, 100), 30) >>> win = GraphWin() >>> circ.draw(win) The first line creates a circle with radius 30 centered at (100,100). We used the Point constructor to create a location for the center of the circle. The last line is a request to the Circle object circ to draw itself into the GraphWin object win. Python Programming, 2/e 165 Python Programming, 1/e

166 Using Graphical Objects
The draw method uses information about the center and radius of the circle from the instance variable. Python Programming, 2/e 166 Python Programming, 1/e

167 Using Graphical Objects
It’s possible for two different variables to refer to the same object – changes made to the object through one variable will be visible to the other. >>> leftEye = Circle(Point(80,50), 5) >>> leftEye.setFill('yellow') >>> leftEye.setOutline('red') >>> rightEye = leftEye >>> rightEye.move(20,0) The idea is to create the left eye and copy that to the right eye which gets moved 20 units. Python Programming, 2/e 167 Python Programming, 1/e

168 Using Graphical Objects
The assignment rightEye = leftEye makes rightEye and leftEye refer to the same circle! The situation where two variables refer to the same object is called aliasing. Python Programming, 2/e 168 Python Programming, 1/e

169 Using Graphical Objects
Python Programming, 2/e 169 Python Programming, 1/e

170 Using Graphical Objects
There are two ways to get around this. We could make two separate circles, one for each eye: >>> leftEye = Circle(Point(80, 50), 5) >>> leftEye.setFill('yellow') >>> leftEye.setOutline('red') >>> rightEye = Circle(Point(100, 50), 5) >>> rightEye.setFill('yellow') >>> rightEye.setOutline('red') Python Programming, 2/e 170 Python Programming, 1/e

171 Using Graphical Objects
The graphics library has a better solution. Graphical objects have a clone method that will make a copy of the object! >>> # Correct way to create two circles, using clone >>> leftEye = Circle(Point(80, 50), 5) >>> leftEye.setFill('yellow') >>> leftEye.setOutline('red') >>> rightEye = leftEye.clone() # rightEye is an exact copy of the left >>> rightEye.move(20, 0) Python Programming, 2/e 171 Python Programming, 1/e

172 Graphing Future Value/ Choosing Coordinates
Python Programming, 2/e 172 Python Programming, 1/e

173 Graphing Future Value/ Choosing Coordinates
Python Programming, 2/e 173 Python Programming, 1/e

174 Interactive Graphics In a GUI environment, users typically interact with their applications by clicking on buttons, choosing items from menus, and typing information into on- screen text boxes. Event-driven programming draws interface elements (widgets) on the screen and then waits for the user to do something. Python Programming, 2/e 174 Python Programming, 1/e

175 Interactive Graphics An event is generated whenever a user moves the mouse, clicks the mouse, or types a key on the keyboard. An event is an object that encapsulates information about what just happened! The event object is sent to the appropriate part of the program to be processed, for example, a button event. Python Programming, 2/e 175 Python Programming, 1/e

176 Interactive Graphics The graphics module hides the underlying, low-level window management and provides two simple ways to get user input in a GraphWin. Python Programming, 2/e 176 Python Programming, 1/e

177 Getting Mouse Clicks We can get graphical information from the user via the getMouse method of the GraphWin class. When getMouse is invoked on a GraphWin, the program pauses and waits for the user to click the mouse somewhere in the window. The spot where the user clicked is returned as a Point. Python Programming, 2/e 177 Python Programming, 1/e

178 Getting Mouse Clicks The following code reports the coordinates of a mouse click: from graphics import * win = GraphWin("Click Me!") p = win.getMouse() print("You clicked", p.getX(), p.getY()) We can use the accessors like getX and getY or other methods on the point returned. Python Programming, 2/e 178 Python Programming, 1/e

179 Getting Mouse Clicks # triangle.pyw
# Interactive graphics program to draw a triangle from graphics import * def main(): win = GraphWin("Draw a Triangle") win.setCoords(0.0, 0.0, 10.0, 10.0) message = Text(Point(5, 0.5), "Click on three points") message.draw(win) # Get and draw three vertices of triangle p1 = win.getMouse() p1.draw(win) p2 = win.getMouse() p2.draw(win) p3 = win.getMouse() p3.draw(win) Python Programming, 2/e 179 Python Programming, 1/e

180 Getting Mouse Clicks # Use Polygon object to draw the triangle
triangle = Polygon(p1,p2,p3) triangle.setFill("peachpuff") triangle.setOutline("cyan") triangle.draw(win) # Wait for another click to exit message.setText("Click anywhere to quit.") win.getMouse() main() Python Programming, 2/e 180 Python Programming, 1/e

181 Getting Mouse Clicks Python Programming, 2/e 181

182 Getting Mouse Clicks Notes:
If you are programming in a windows environment, using the .pyw extension on your file will cause the Python shell window to not display when you double-click the program icon. There is no triangle class. Rather, we use the general polygon class, which takes any number of points and connects them into a closed shape. Python Programming, 2/e 182 Python Programming, 1/e

183 Getting Mouse Clicks Once you have three points, creating a triangle polygon is easy: triangle = Polygon(p1, p2, p3) A single text object is created and drawn near the beginning of the program. message = Text(Point(5,0.5), "Click on three points") message.draw(win) To change the prompt, just change the text to be displayed. message.setText("Click anywhere to quit.") Python Programming, 2/e 183 Python Programming, 1/e

184 Handling Textual Input
The triangle program’s input was done completely through mouse clicks. There’s also an Entry object that can get keyboard input. The Entry object draws a box on the screen that can contain text. It understands setText and getText, with one difference that the input can be edited. Python Programming, 2/e 184 Python Programming, 1/e

185 Handling Textual Input
Python Programming, 2/e 185 Python Programming, 1/e

186 Handling Textual Input
# convert_gui.pyw # Program to convert Celsius to Fahrenheit using a simple # graphical interface. from graphics import * def main(): win = GraphWin("Celsius Converter", 300, 200) win.setCoords(0.0, 0.0, 3.0, 4.0) # Draw the interface Text(Point(1,3), " Celsius Temperature:").draw(win) Text(Point(1,1), "Fahrenheit Temperature:").draw(win) input = Entry(Point(2,3), 5) input.setText("0.0") input.draw(win) output = Text(Point(2,1),"") output.draw(win) button = Text(Point(1.5,2.0),"Convert It") button.draw(win) Rectangle(Point(1,1.5), Point(2,2.5)).draw(win) Python Programming, 2/e 186 Python Programming, 1/e

187 Handling Textual Input
# wait for a mouse click win.getMouse() # convert input celsius = eval(input.getText()) fahrenheit = 9.0/5.0 * celsius + 32 # display output and change button output.setText(fahrenheit) button.setText("Quit") # wait for click and then quit win.close() main() Python Programming, 2/e 187 Python Programming, 1/e

188 Handling Textual Input
Python Programming, 2/e 188 Python Programming, 1/e

189 Handling Textual Input
When run, this program produces a window with an entry box for typing in the Celsius temperature and a button to “do” the conversion. The button is for show only! We are just waiting for a mouse click anywhere in the window. Python Programming, 2/e 189 Python Programming, 1/e

190 Handling Textual Input
Initially, the input entry box is set to contain “0.0”. The user can delete this value and type in another value. The program pauses until the user clicks the mouse – we don’t care where so we don’t store the point! Python Programming, 2/e 190 Python Programming, 1/e

191 Handling Textual Input
The input is processed in three steps: The value entered is converted into a number with eval. This number is converted to degrees Fahrenheit. This number is then converted to a string and formatted for display in the output text area. Python Programming, 2/e 191 Python Programming, 1/e

192 Python Programming: An Introduction to Computer Science
Chapter 5 Sequences: Strings, Lists, and Files Python Programming, 2/e

193 Objectives To understand the string data type and how strings are represented in the computer. To be familiar with various operations that can be performed on strings through built-in functions and the string library. Python Programming, 2/e

194 Objectives (cont.) To understand the basic idea of sequences and indexing as they apply to Python strings and lists. To be able to apply string formatting to produce attractive, informative program output. To understand basic file processing concepts and techniques for reading and writing text files in Python. Python Programming, 2/e

195 Objectives (cont.) To understand basic concepts of cryptography.
To be able to understand and write programs that process textual information. Python Programming, 2/e

196 The String Data Type The most common use of personal computers is word processing. Text is represented in programs by the string data type. A string is a sequence of characters enclosed within quotation marks (") or apostrophes ('). Python Programming, 2/e

197 The String Data Type >>> str1="Hello"
>>> str2='spam' >>> print(str1, str2) Hello spam >>> type(str1) <class 'str'> >>> type(str2) Python Programming, 2/e

198 The String Data Type Getting a string as input
>>> firstName = input("Please enter your name: ") Please enter your name: John >>> print("Hello", firstName) Hello John Notice that the input is not evaluated. We want to store the typed characters, not to evaluate them as a Python expression. Python Programming, 2/e

199 The String Data Type We can access the individual characters in a string through indexing. The positions in a string are numbered from the left, starting with 0. The general form is <string>[<expr>], where the value of expr determines which character is selected from the string. Python Programming, 2/e

200 The String Data Type H e l o B b 0 1 2 3 4 5 6 7 8
>>> greet = "Hello Bob" >>> greet[0] 'H' >>> print(greet[0], greet[2], greet[4]) H l o >>> x = 8 >>> print(greet[x - 2]) B Python Programming, 2/e

201 The String Data Type H e l o B b In a string of n characters, the last character is at position n-1 since we start counting with 0. We can index from the right side using negative indexes. >>> greet[-1] 'b' >>> greet[-3] 'B' Python Programming, 2/e

202 The String Data Type Indexing returns a string containing a single character from a larger string. We can also access a contiguous sequence of characters, called a substring, through a process called slicing. Python Programming, 2/e

203 The String Data Type Slicing: <string>[<start>:<end>] start and end should both be ints The slice contains the substring beginning at position start and runs up to but doesn’t include the position end. Python Programming, 2/e

204 The String Data Type H e l o B b 0 1 2 3 4 5 6 7 8
>>> greet[0:3] 'Hel' >>> greet[5:9] ' Bob' >>> greet[:5] 'Hello' >>> greet[5:] >>> greet[:] 'Hello Bob' Python Programming, 2/e

205 The String Data Type If either expression is missing, then the start or the end of the string are used. Can we put two strings together into a longer string? Concatenation “glues” two strings together (+) Repetition builds up a string by multiple concatenations of a string with itself (*) Python Programming, 2/e

206 The String Data Type The function len will return the length of a string. >>> "spam" + "eggs" 'spameggs' >>> "Spam" + "And" + "Eggs" 'SpamAndEggs' >>> 3 * "spam" 'spamspamspam' >>> "spam" * 5 'spamspamspamspamspam' >>> (3 * "spam") + ("eggs" * 5) 'spamspamspameggseggseggseggseggs' Python Programming, 2/e

207 The String Data Type >>> len("spam") 4
>>> for ch in "Spam!": print (ch, end=" ") S p a m ! Python Programming, 2/e

208 The String Data Type Operator Meaning + Concatenation * Repetition
Indexing <string>[:] Slicing len(<string>) Length for <var> in <string> Iteration through characters Python Programming, 2/e

209 Simple String Processing
Usernames on a computer system First initial, first seven characters of last name # get user’s first and last names first = input("Please enter your first name (all lowercase): ") last = input("Please enter your last name (all lowercase): ") # concatenate first initial with 7 chars of last name uname = first[0] + last[:7] Python Programming, 2/e

210 Simple String Processing
>>> Please enter your first name (all lowercase): john Please enter your last name (all lowercase): doe uname = jdoe Please enter your first name (all lowercase): donna Please enter your last name (all lowercase): rostenkowski uname = drostenk Python Programming, 2/e

211 Simple String Processing
Another use – converting an int that stands for the month into the three letter abbreviation for that month. Store all the names in one big string: “JanFebMarAprMayJunJulAugSepOctNovDec” Use the month number as an index for slicing this string: monthAbbrev = months[pos:pos+3] Python Programming, 2/e

212 Simple String Processing
Month Number Position Jan 1 Feb 2 3 Mar 6 Apr 4 9 To get the correct position, subtract one from the month number and multiply by three Python Programming, 2/e

213 Simple String Processing
# month.py # A program to print the abbreviation of a month, given its number def main(): # months is used as a lookup table months = "JanFebMarAprMayJunJulAugSepOctNovDec" n = eval(input("Enter a month number (1-12): ")) # compute starting position of month n in months pos = (n-1) * 3 # Grab the appropriate slice from months monthAbbrev = months[pos:pos+3] # print the result print ("The month abbreviation is", monthAbbrev + ".") main() Python Programming, 2/e

214 Simple String Processing
>>> main() Enter a month number (1-12): 1 The month abbreviation is Jan. Enter a month number (1-12): 12 The month abbreviation is Dec. One weakness – this method only works where the potential outputs all have the same length. How could you handle spelling out the months? Python Programming, 2/e

215 Strings, Lists, and Sequences
It turns out that strings are really a special kind of sequence, so these operations also apply to sequences! >>> [1,2] + [3,4] [1, 2, 3, 4] >>> [1,2]*3 [1, 2, 1, 2, 1, 2] >>> grades = ['A', 'B', 'C', 'D', 'F'] >>> grades[0] 'A' >>> grades[2:4] ['C', 'D'] >>> len(grades) 5 Python Programming, 2/e

216 Strings, Lists, and Sequences
Strings are always sequences of characters, but lists can be sequences of arbitrary values. Lists can have numbers, strings, or both! myList = [1, "Spam ", 4, "U"] Python Programming, 2/e

217 Strings, Lists, and Sequences
We can use the idea of a list to make our previous month program even simpler! We change the lookup table for months to a list: months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] Python Programming, 2/e

218 Strings, Lists, and Sequences
To get the months out of the sequence, do this: monthAbbrev = months[n-1] Rather than this: monthAbbrev = months[pos:pos+3] Python Programming, 2/e

219 Strings, Lists, and Sequences
# month2.py # A program to print the month name, given it's number. # This version uses a list as a lookup table. def main(): # months is a list used as a lookup table months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] n = eval(input("Enter a month number (1-12): ")) print ("The month abbreviation is", months[n-1] + ".") main() Note that the months line overlaps a line. Python knows that the expression isn’t complete until the closing ] is encountered. Python Programming, 2/e

220 Strings, Lists, and Sequences
# month2.py # A program to print the month name, given it's number. # This version uses a list as a lookup table. def main(): # months is a list used as a lookup table months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] n = eval(input("Enter a month number (1-12): ")) print ("The month abbreviation is", months[n-1] + ".") main() Since the list is indexed starting from 0, the n-1 calculation is straight-forward enough to put in the print statement without needing a separate step. Python Programming, 2/e

221 Strings, Lists, and Sequences
This version of the program is easy to extend to print out the whole month name rather than an abbreviation! months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] Python Programming, 2/e

222 Strings, Lists, and Sequences
Lists are mutable, meaning they can be changed. Strings can not be changed. >>> myList = [34, 26, 15, 10] >>> myList[2] 15 >>> myList[2] = 0 >>> myList [34, 26, 0, 10] >>> myString = "Hello World" >>> myString[2] 'l' >>> myString[2] = "p" Traceback (most recent call last): File "<pyshell#16>", line 1, in -toplevel- myString[2] = "p" TypeError: object doesn't support item assignment Python Programming, 2/e

223 Strings and Secret Codes
Inside the computer, strings are represented as sequences of 1’s and 0’s, just like numbers. A string is stored as a sequence of binary numbers, one number per character. It doesn’t matter what value is assigned as long as it’s done consistently. Python Programming, 2/e

224 Strings and Secret Codes
In the early days of computers, each manufacturer used their own encoding of numbers for characters. ASCII system (American Standard Code for Information Interchange) uses 127 bit codes Python supports Unicode (100,000+ characters) Python Programming, 2/e

225 Strings and Secret Codes
The ord function returns the numeric (ordinal) code of a single character. The chr function converts a numeric code to the corresponding character. >>> ord("A") 65 >>> ord("a") 97 >>> chr(97) 'a' >>> chr(65) 'A' Python Programming, 2/e

226 Strings and Secret Codes
Using ord and char we can convert a string into and out of numeric form. The encoding algorithm is simple: get the message to encode for each character in the message: print the letter number of the character A for loop iterates over a sequence of objects, so the for loop looks like: for ch in <string> Python Programming, 2/e

227 Strings and Secret Codes
# text2numbers.py # A program to convert a textual message into a sequence of # numbers, utlilizing the underlying Unicode encoding. def main(): print("This program converts a textual message into a sequence") print ("of numbers representing the Unicode encoding of the message.\n") # Get the message to encode message = input("Please enter the message to encode: ") print("\nHere are the Unicode codes:") # Loop through the message and print out the Unicode values for ch in message: print(ord(ch), end=" ") print() main() Python Programming, 2/e

228 Strings and Secret Codes
We now have a program to convert messages into a type of “code”, but it would be nice to have a program that could decode the message! The outline for a decoder: get the sequence of numbers to decode message = “” for each number in the input: convert the number to the appropriate character add the character to the end of the message print the message Python Programming, 2/e

229 Strings and Secret Codes
The variable message is an accumulator variable, initially set to the empty string, the string with no characters (“”). Each time through the loop, a number from the input is converted to the appropriate character and appended to the end of the accumulator. Python Programming, 2/e

230 Strings and Secret Codes
How do we get the sequence of numbers to decode? Read the input as a single string, then split it apart into substrings, each of which represents one number. Python Programming, 2/e

231 Strings and Secret Codes
The new algorithm get the sequence of numbers as a string, inString message = “” for each of the smaller strings: change the string of digits into the number it represents append the ASCII character for that number to message print message Strings are objects and have useful methods associated with them Python Programming, 2/e

232 Strings and Secret Codes
One of these methods is split. This will split a string into substrings based on spaces. >>> "Hello string methods!".split() ['Hello', 'string', 'methods!'] Python Programming, 2/e

233 Strings and Secret Codes
Split can be used on characters other than space, by supplying the character as a parameter. >>> "32,24,25,57".split(",") ['32', '24', '25', '57'] >>> Python Programming, 2/e

234 Strings and Secret Codes
How can we convert a string containing digits into a number? Use our friend eval. >>> numStr = "500" >>> eval(numStr) 500 >>> x = eval(input("Enter a number ")) Enter a number 3.14 >>> print x 3.14 >>> type (x) <type 'float'> Python Programming, 2/e

235 Strings and Secret Codes
# numbers2text.py # A program to convert a sequence of Unicode numbers into # a string of text. def main(): print ("This program converts a sequence of Unicode numbers into") print ("the string of text that it represents.\n") # Get the message to encode inString = input("Please enter the Unicode-encoded message: ") # Loop through each substring and build Unicde message message = "" for numStr in inString.split(i): # convert the (sub)string to a number codeNum = eval(numStr) # append character to message message = message + chr(codeNum) print("\nThe decoded message is:", message) main() Python Programming, 2/e

236 Strings and Secret Codes
The split function produces a sequence of strings. numString gets each successive substring. Each time through the loop, the next substring is converted to the appropriate Unicode character and appended to the end of message. Python Programming, 2/e

237 Strings and Secret Codes
This program converts a textual message into a sequence of numbers representing the Unicode encoding of the message. Please enter the message to encode: CS120 is fun! Here are the Unicode codes: This program converts a sequence of Unicode numbers into the string of text that it represents. Please enter the ASCII-encoded message: The decoded message is: CS120 is fun! Python Programming, 2/e

238 Other String Methods There are a number of other string methods. Try them all! s.capitalize() – Copy of s with only the first character capitalized s.title() – Copy of s; first character of each word capitalized s.center(width) – Center s in a field of given width Python Programming, 2/e

239 Other String Operations
s.count(sub) – Count the number of occurrences of sub in s s.find(sub) – Find the first position where sub occurs in s s.join(list) – Concatenate list of strings into one large string using s as separator. s.ljust(width) – Like center, but s is left-justified Python Programming, 2/e

240 Other String Operations
s.lower() – Copy of s in all lowercase letters s.lstrip() – Copy of s with leading whitespace removed s.replace(oldsub, newsub) – Replace occurrences of oldsub in s with newsub s.rfind(sub) – Like find, but returns the right-most position s.rjust(width) – Like center, but s is right-justified Python Programming, 2/e

241 Other String Operations
s.rstrip() – Copy of s with trailing whitespace removed s.split() – Split s into a list of substrings s.upper() – Copy of s; all characters converted to uppercase Python Programming, 2/e

242 From Encoding to Encryption
The process of encoding information for the purpose of keeping it secret or transmitting it privately is called encryption. Cryptography is the study of encryption methods. Encryption is used when transmitting credit card and other personal information to a web site. Python Programming, 2/e

243 From Encoding to Encryption
Strings are represented as a sort of encoding problem, where each character in the string is represented as a number that’s stored in the computer. The code that is the mapping between character and number is an industry standard, so it’s not “secret”. Python Programming, 2/e

244 From Encoding to Encryption
The encoding/decoding programs we wrote use a substitution cipher, where each character of the original message, known as the plaintext, is replaced by a corresponding symbol in the cipher alphabet. The resulting code is known as the ciphertext. Python Programming, 2/e

245 From Encoding to Encryption
This type of code is relatively easy to break. Each letter is always encoded with the same symbol, so using statistical analysis on the frequency of the letters and trial and error, the original message can be determined. Python Programming, 2/e

246 From Encoding to Encryption
Modern encryption converts messages into numbers. Sophisticated mathematical formulas convert these numbers into new numbers – usually this transformation consists of combining the message with another value called the “key” Python Programming, 2/e

247 From Encoding to Encryption
To decrypt the message, the receiving end needs an appropriate key so the encoding can be reversed. In a private key system the same key is used for encrypting and decrypting messages. Everyone you know would need a copy of this key to communicate with you, but it needs to be kept a secret. Python Programming, 2/e

248 From Encoding to Encryption
In public key encryption, there are separate keys for encrypting and decrypting the message. In public key systems, the encryption key is made publicly available, while the decryption key is kept private. Anyone with the public key can send a message, but only the person who holds the private key (decryption key) can decrypt it. Python Programming, 2/e

249 Input/Output as String Manipulation
Often we will need to do some string operations to prepare our string data for output (“pretty it up”) Let’s say we want to enter a date in the format “05/24/2003” and output “May 24, 2003.” How could we do that? Python Programming, 2/e

250 Input/Output as String Manipulation
Input the date in mm/dd/yyyy format (dateStr) Split dateStr into month, day, and year strings Convert the month string into a month number Use the month number to lookup the month name Create a new date string in the form “Month Day, Year” Output the new date string Python Programming, 2/e

251 Input/Output as String Manipulation
The first two lines are easily implemented! dateStr = input("Enter a date (mm/dd/yyyy): ") monthStr, dayStr, yearStr = dateStr.split("/") The date is input as a string, and then “unpacked” into the three variables by splitting it at the slashes and using simultaneous assignment. Python Programming, 2/e

252 Input/Output as String Manipulation
Next step: Convert monthStr into a number We can use the int function on monthStr to convert "05", for example, into the integer 5. (int("05") = 5) Python Programming, 2/e

253 Input/Output as String Manipulation
Note: eval would work, but for the leading 0 >>> int("05") 5 >>> eval("05") Traceback (most recent call last): File "<pyshell#9>", line 1, in <module> eval("05") File "<string>", line 1 05 ^ SyntaxError: invalid token This is historical baggage. A leading 0 used to be used for base 8 (octal) literals in Python. Python Programming, 2/e

254 Input/Output as String Manipulation
months = [“January”, “February”, …, “December”] monthStr = months[int(monthStr) – 1] Remember that since we start counting at 0, we need to subtract one from the month. Now let’s concatenate the output string together! Python Programming, 2/e

255 Input/Output as String Manipulation
print ("The converted date is:", monthStr, dayStr+",", yearStr) Notice how the comma is appended to dayStr with concatenation! >>> main() Enter a date (mm/dd/yyyy): 01/23/2010 The converted date is: January 23, 2010 Python Programming, 2/e

256 Input/Output as String Manipulation
Sometimes we want to convert a number into a string. We can use the str function. >>> str(500) '500' >>> value = 3.14 >>> str(value) '3.14' >>> print("The value is", str(value) + ".") The value is 3.14. Python Programming, 2/e

257 Input/Output as String Manipulation
If value is a string, we can concatenate a period onto the end of it. If value is an int, what happens? >>> value = 3.14 >>> print("The value is", value + ".") The value is Traceback (most recent call last): File "<pyshell#10>", line 1, in -toplevel- print "The value is", value + "." TypeError: unsupported operand type(s) for +: 'float' and 'str' Python Programming, 2/e

258 Input/Output as String Manipulation
We now have a complete set of type conversion operations: Function Meaning float(<expr>) Convert expr to a floating point value int(<expr>) Convert expr to an integer value str(<expr>) Return a string representation of expr eval(<string>) Evaluate string as an expression Python Programming, 2/e

259 String Formatting String formatting is an easy way to get beautiful output! Change Counter Please enter the count of each coin type. Quarters: 6 Dimes: 0 Nickels: 0 Pennies: 0 The total value of your change is 1.5 Shouldn’t that be more like $1.50?? Python Programming, 2/e

260 String Formatting We can format our output by modifying the print statement as follows: print("The total value of your change is ${0:0.2f}".format(total)) Now we get something like: The total value of your change is $1.50 Key is the string format method. Python Programming, 2/e

261 String Formatting <template-string>.format(<values>)
{} within the template-string mark “slots” into which the values are inserted. Each slot has description that includes format specifier telling Python how the value for the slot should appear. Python Programming, 2/e

262 String Formatting print("The total value of your change is ${0:0.2f}".format(total) The template contains a single slot with the description: 0:0.2f Form of description: <index>:<format-specifier> Index tells which parameter to insert into the slot. In this case, total. Python Programming, 2/e

263 String Formatting The formatting specifier has the form: <width>.<precision><type> f means "fixed point" number <width> tells us how many spaces to use to display the value. 0 means to use as much space as necessary. <precision> is the number of decimal places. Python Programming, 2/e

264 String Formatting >>> "Hello {0} {1}, you may have won ${2}" .format("Mr.", "Smith", 10000) 'Hello Mr. Smith, you may have won $10000' >>> 'This int, {0:5}, was placed in a field of width 5'.format(7) 'This int, 7, was placed in a field of width 5' >>> 'This int, {0:10}, was placed in a field of witdh 10'.format(10) 'This int, , was placed in a field of witdh 10' >>> 'This float, {0:10.5}, has width 10 and precision 5.'.format( ) 'This float, , has width 10 and precision 5.' >>> 'This float, {0:10.5f}, is fixed at 5 decimal places.'.format( ) 'This float, , has width 0 and precision 5.' Python Programming, 2/e

265 String Formatting If the width is wider than needed, numeric values are right-justified and strings are left- justified, by default. You can also specify a justification before the width. >>> "left justification: {0:<5}.format("Hi!") 'left justification: Hi! ' >>> "right justification: {0:>5}.format("Hi!") 'right justification: Hi!' >>> "centered: {0:^5}".format("Hi!") 'centered: Hi! ' Python Programming, 2/e

266 Better Change Counter With what we know now about floating point numbers, we might be uneasy about using them in a money situation. One way around this problem is to keep trace of money in cents using an int or long int, and convert it into dollars and cents when output. Python Programming, 2/e

267 Better Change Counter If total is a value in cents (an int), dollars = total//100 cents = total%100 Cents is printed using width 0>2 to right-justify it with leading 0s (if necessary) into a field of width 2. Thus 5 cents becomes '05' Python Programming, 2/e

268 Better Change Counter # change2.py
# A program to calculate the value of some change in dollars. # This version represents the total cash in cents. def main(): print ("Change Counter\n") print ("Please enter the count of each coin type.") quarters = eval(input("Quarters: ")) dimes = eval(input("Dimes: ")) nickels = eval(input("Nickels: ")) pennies = eval(input("Pennies: ")) total = quarters * 25 + dimes * 10 + nickels * 5 + pennies print ("The total value of your change is ${0}.{1:0>2}" .format(total//100, total%100)) Python Programming, 2/e

269 Better Change Counter >>> main() Change Counter
Please enter the count of each coin type. Quarters: 0 Dimes: 0 Nickels: 0 Pennies: 1 The total value of your change is $0.01 >>> main() Change Counter Please enter the count of each coin type. Quarters: 12 Dimes: 1 Nickels: 0 Pennies: 4 The total value of your change is $3.14 Python Programming, 2/e

270 Files: Multi-line Strings
A file is a sequence of data that is stored in secondary memory (disk drive). Files can contain any data type, but the easiest to work with are text. A file usually contains more than one line of text. Python uses the standard newline character (\n) to mark line breaks. Python Programming, 2/e

271 Multi-Line Strings Hello World Goodbye 32
When stored in a file: Hello\nWorld\n\nGoodbye 32\n Python Programming, 2/e

272 Multi-Line Strings This is exactly the same thing as embedding \n in print statements. Remember, these special characters only affect things when printed. They don’t do anything during evaluation. Python Programming, 2/e

273 File Processing The process of opening a file involves associating a file on disk with an object in memory. We can manipulate the file by manipulating this object. Read from the file Write to the file Python Programming, 2/e

274 File Processing When done with the file, it needs to be closed. Closing the file causes any outstanding operations and other bookkeeping for the file to be completed. In some cases, not properly closing a file could result in data loss. Python Programming, 2/e

275 File Processing Reading a file into a word processor File opened
Contents read into RAM File closed Changes to the file are made to the copy stored in memory, not on the disk. Python Programming, 2/e

276 File Processing Saving a word processing file
The original file on the disk is reopened in a mode that will allow writing (this actually erases the old contents) File writing operations copy the version of the document in memory to the disk The file is closed Python Programming, 2/e

277 File Processing Working with text files in Python
Associate a disk file with a file object using the open function <filevar> = open(<name>, <mode>) Name is a string with the actual file name on the disk. The mode is either ‘r’ or ‘w’ depending on whether we are reading or writing the file. Infile = open("numbers.dat", "r") Python Programming, 2/e

278 File Methods <file>.read() – returns the entire remaining contents of the file as a single (possibly large, multi-line) string <file>.readline() – returns the next line of the file. This is all text up to and including the next newline character <file>.readlines() – returns a list of the remaining lines in the file. Each list item is a single line including the newline characters. Python Programming, 2/e

279 File Processing First, prompt the user for a file name
# printfile.py # Prints a file to the screen. def main(): fname = input("Enter filename: ") infile = open(fname,'r') data = infile.read() print(data) main() First, prompt the user for a file name Open the file for reading The file is read as one string and stored in the variable data Python Programming, 2/e

280 File Processing readline can be used to read the next line from a file, including the trailing newline character infile = open(someFile, "r") for i in range(5): line = infile.readline() print line[:-1] This reads the first 5 lines of a file Slicing is used to strip out the newline characters at the ends of the lines Python Programming, 2/e

281 File Processing Another way to loop through the contents of a file is to read it in with readlines and then loop through the resulting list. infile = open(someFile, "r") for line in infile.readlines(): # Line processing here infile.close() Python Programming, 2/e

282 File Processing Python treats the file itself as a sequence of lines!
Infile = open(someFile, "r") for line in infile: # process the line here infile.close() Python Programming, 2/e

283 File Processing Opening a file for writing prepares the file to receive data If you open an existing file for writing, you wipe out the file’s contents. If the named file does not exist, a new one is created. Outfile = open("mydata.out", "w") print(<expressions>, file=Outfile) Python Programming, 2/e

284 Example Program: Batch Usernames
Batch mode processing is where program input and output are done through files (the program is not designed to be interactive) Let’s create usernames for a computer system where the first and last names come from an input file. Python Programming, 2/e

285 Example Program: Batch Usernames
# userfile.py # Program to create a file of usernames in batch mode. def main(): print ("This program creates a file of usernames from a") print ("file of names.") # get the file names infileName = input("What file are the names in? ") outfileName = input("What file should the usernames go in? ") # open the files infile = open(infileName, 'r') outfile = open(outfileName, 'w') Python Programming, 2/e

286 Example Program: Batch Usernames
# process each line of the input file for line in infile: # get the first and last names from line first, last = line.split() # create a username uname = (first[0]+last[:7]).lower() # write it to the output file print(uname, file=outfile) # close both files infile.close() outfile.close() print("Usernames have been written to", outfileName) Python Programming, 2/e

287 Example Program: Batch Usernames
Things to note: It’s not unusual for programs to have multiple files open for reading and writing at the same time. The lower method is used to convert the names into all lower case, in the event the names are mixed upper and lower case. Python Programming, 2/e

288 Python Programming: An Introduction to Computer Science
Chapter 6 Defining Functions Python Programming, 2/e

289 Objectives To understand why programmers divide programs up into sets of cooperating functions. To be able to define new functions in Python. To understand the details of function calls and parameter passing in Python. Python Programming, 2/e

290 Objectives (cont.) To write programs that use functions to reduce code duplication and increase program modularity. Python Programming, 2/e

291 The Function of Functions
So far, we’ve seen four different types of functions: Our programs comprise a single function called main(). Built-in Python functions (abs) Functions from the standard libraries (math.sqrt) Functions from the graphics module (p.getX()) Python Programming, 2/e Python Programming, 1/e

292 The Function of Functions
Having similar or identical code in more than one place has some drawbacks. Issue one: writing the same code twice or more. Issue two: This same code must be maintained in two separate places. Functions can be used to reduce code duplication and make programs more easily understood and maintained. Python Programming, 2/e

293 Functions, Informally A function is like a subprogram, a small program inside of a program. The basic idea – we write a sequence of statements and then give that sequence a name. We can then execute this sequence at any time by referring to the name. Python Programming, 2/e

294 Functions, Informally The part of the program that creates a function is called a function definition. When the function is used in a program, we say the definition is called or invoked. Python Programming, 2/e

295 Functions, Informally Happy Birthday lyrics… def main(): print("Happy birthday to you!" ) print("Happy birthday to you!" ) print("Happy birthday, dear Fred...") print("Happy birthday to you!") Gives us this… >>> main() Happy birthday to you! Happy birthday to you! Happy birthday, dear Fred... Happy birthday to you! Python Programming, 2/e

296 Functions, Informally There’s some duplicated code in the program! (print("Happy birthday to you!")) We can define a function to print out this line: def happy(): print("Happy birthday to you!") With this function, we can rewrite our program. Python Programming, 2/e

297 Functions, Informally The new program – def singFred(): happy() happy() print("Happy birthday, dear Fred...") happy() Gives us this output – >>> singFred() Happy birthday to you! Happy birthday to you! Happy birthday, dear Fred... Happy birthday to you! Python Programming, 2/e

298 Functions, Informally Creating this function saved us a lot of typing!
What if it’s Lucy’s birthday? We could write a new singLucy function! def singLucy(): happy() happy() print("Happy birthday, dear Lucy...") happy() Python Programming, 2/e

299 Functions, Informally We could write a main program to sing to both Lucy and Fred def main(): singFred() print() singLucy() This gives us this new output >>> main() Happy birthday to you! Happy birthday to you! Happy birthday, dear Fred.. Happy birthday to you! Happy birthday to you! Happy birthday to you! Happy birthday, dear Lucy... Happy birthday to you! Python Programming, 2/e

300 Functions, Informally This is working great! But… there’s still a lot of code duplication. The only difference between singFred and singLucy is the name in the third print statement. These two routines could be collapsed together by using a parameter. Python Programming, 2/e

301 Functions, Informally The generic function sing def sing(person): happy() happy() print("Happy birthday, dear", person + ".“) happy() This function uses a parameter named person. A paramater is a variable that is initialized when the function is called. Python Programming, 2/e

302 Functions, Informally Our new output – >>> sing("Fred") Happy birthday to you! Happy birthday to you! Happy birthday, dear Fred. Happy birthday to you! We can put together a new main program! Python Programming, 2/e

303 Functions, Informally Our new main program: def main(): sing("Fred") print() sing("Lucy") Gives us this output: >>> main() Happy birthday to you! Happy birthday to you! Happy birthday, dear Fred. Happy birthday to you! Happy birthday to you! Happy birthday to you! Happy birthday, dear Lucy. Happy birthday to you! Python Programming, 2/e

304 Future Value with a Function
In the future value graphing program, we see similar code twice: # Draw bar for initial principal bar = Rectangle(Point(0, 0), Point(1, principal)) bar.setFill("green") bar.setWidth(2) bar.draw(win) bar = Rectangle(Point(year, 0), Point(year+1, principal)) bar.setFill("green") bar.setWidth(2) bar.draw(win) Python Programming, 2/e

305 Future Value with a Function
To properly draw the bars, we need three pieces of information. The year the bar is for How tall the bar should be The window the bar will be drawn in These three values can be supplied as parameters to the function. Python Programming, 2/e

306 Future Value with a Function
The resulting function looks like this: def drawBar(window, year, height): # Draw a bar in window starting at year with given height bar = Rectangle(Point(year, 0), Point(year+1, height)) bar.setFill("green") bar.setWidth(2) bar.draw(window) To use this function, we supply the three values. If win is a Graphwin, we can draw a bar for year 0 and principal of $2000 using this call: drawBar(win, 0, 2000) Python Programming, 2/e

307 Functions and Parameters: The Details
It makes sense to include the year and the principal in the drawBar function, but why send the window variable? The scope of a variable refers to the places in a program a given variable can be referenced. Python Programming, 2/e

308 Functions and Parameters: The Details
Each function is its own little subprogram. The variables used inside of a function are local to that function, even if they happen to have the same name as variables that appear inside of another function. The only way for a function to see a variable from another function is for that variable to be passed as a parameter. Python Programming, 2/e

309 Functions and Parameters: The Details
Since the GraphWin in the variable win is created inside of main, it is not directly accessible in drawBar. The window parameter in drawBar gets assigned the value of win from main when drawBar is called. Python Programming, 2/e

310 Functions and Parameters: The Details
A function definition looks like this: def <name>(<formal-parameters>): <body> The name of the function must be an identifier Formal-parameters is a possibly empty list of variable names Python Programming, 2/e

311 Functions and Parameters: The Details
Formal parameters, like all variables used in the function, are only accessible in the body of the function. Variables with identical names elsewhere in the program are distinct from the formal parameters and variables inside of the function body. Python Programming, 2/e

312 Functions and Parameters: The Details
A function is called by using its name followed by a list of actual parameters or arguments. <name>(<actual-parameters>) When Python comes to a function call, it initiates a four-step process. Python Programming, 2/e

313 Functions and Parameters: The Details
The calling program suspends execution at the point of the call. The formal parameters of the function get assigned the values supplied by the actual parameters in the call. The body of the function is executed. Control returns to the point just after where the function was called. Python Programming, 2/e

314 Functions and Parameters: The Details
Let’s trace through the following code: sing("Fred") print() sing("Lucy") When Python gets to sing("Fred"), execution of main is temporarily suspended. Python looks up the definition of sing and sees that it has one formal parameter, person. Python Programming, 2/e

315 Functions and Parameters: The Detail
The formal parameter is assigned the value of the actual parameter. It’s as if the following statement had been executed: person = "Fred" Python Programming, 2/e

316 Functions and Parameters: The Details
Note that the variable person has just been initialized. Python Programming, 2/e

317 Functions and Parameters: The Details
At this point, Python begins executing the body of sing. The first statement is another function call, to happy. What happens next? Python suspends the execution of sing and transfers control to happy. happy consists of a single print, which is executed and control returns to where it left off in sing. Python Programming, 2/e

318 Functions and Parameters: The Details
Execution continues in this way with two more trips to happy. When Python gets to the end of sing, control returns to main and continues immediately following the function call. Python Programming, 2/e

319 Functions and Parameters: The Details
Notice that the person variable in sing has disappeared! The memory occupied by local function variables is reclaimed when the function exits. Local variables do not retain any values from one function execution to the next. Python Programming, 2/e

320 Functions and Parameters: The Details
The next statement is the bare print, which produces a blank line. Python encounters another call to sing, and control transfers to the sing function, with the formal parameter “Lucy”. Python Programming, 2/e

321 Functions and Parameters: The Details
The body of sing is executed for Lucy with its three side trips to happy and control returns to main. Python Programming, 2/e

322 Functions and Parameters: The Details
Python Programming, 2/e

323 Functions and Paramters: The Details
One thing not addressed in this example was multiple parameters. In this case the formal and actual parameters are matched up based on position, e.g. the first actual parameter is assigned to the first formal parameter, the second actual parameter is assigned to the second formal parameter, etc. Python Programming, 2/e

324 Functions and Parameters: The Details
As an example, consider the call to drawBar: drawBar(win, 0, principal) When control is passed to drawBar, these parameters are matched up to the formal parameters in the function heading: def drawBar(window, year, height): Python Programming, 2/e

325 Functions and Parameters: The Details
The net effect is as if the function body had been prefaced with three assignment statements: window = win year = 0 height = principal Python Programming, 2/e

326 Getting Results from a Function
Passing parameters provides a mechanism for initializing the variables in a function. Parameters act as inputs to a function. We can call a function many times and get different results by changing its parameters. Python Programming, 2/e

327 Functions That Return Values
We’ve already seen numerous examples of functions that return values to the caller. discRt = math.sqrt(b*b – 4*a*c) The value b*b – 4*a*c is the actual parameter of math.sqrt. We say sqrt returns the square root of its argument. Python Programming, 2/e

328 Functions That Return Values
This function returns the square of a number: def square(x): return x*x When Python encounters return, it exits the function and returns control to the point where the function was called. In addition, the value(s) provided in the return statement are sent back to the caller as an expression result. Python Programming, 2/e

329 Functions That Return Values
>>> square(3) 9 >>> print(square(4)) 16 >>> x = 5 >>> y = square(x) >>> print(y) 25 >>> print(square(x) + square(3)) 34 Python Programming, 2/e

330 Functions That Return Values
We can use the square function to write a routine to calculate the distance between (x1,y1) and (x2,y2). def distance(p1, p2): dist = math.sqrt(square(p2.getX() - p1.getX()) + square(p2.getY() - p1.getY())) return dist Python Programming, 2/e

331 Functions That Return Values
Sometimes a function needs to return more than one value. To do this, simply list more than one expression in the return statement. def sumDiff(x, y): sum = x + y diff = x – y return sum, diff Python Programming, 2/e

332 Functions That Return Values
When calling this function, use simultaneous assignment. num1, num2 = eval(input("Enter two numbers (num1, num2) ")) s, d = sumDiff(num1, num2) print("The sum is", s, "and the difference is", d) As before, the values are assigned based on position, so s gets the first value returned (the sum), and d gets the second (the difference). Python Programming, 2/e

333 Functions That Return Values
One “gotcha” – all Python functions return a value, whether they contain a return statement or not. Functions without a return hand back a special object, denoted None. A common problem is writing a value-returning function and omitting the return! Python Programming, 2/e

334 Functions That Return Values
If your value-returning functions produce strange messages, check to make sure you remembered to include the return! Python Programming, 2/e

335 Functions that Modify Parameters
Return values are the main way to send information from a function back to the caller. Sometimes, we can communicate back to the caller by making changes to the function parameters. Understanding when and how this is possible requires the mastery of some subtle details about how assignment works and the relationship between actual and formal parameters. Python Programming, 2/e

336 Functions that Modify Parameters
Suppose you are writing a program that manages bank accounts. One function we would need to do is to accumulate interest on the account. Let’s look at a first-cut at the function. def addInterest(balance, rate): newBalance = balance * (1 + rate) balance = newBalance Python Programming, 2/e

337 Functions that Modify Parameters
The intent is to set the balance of the account to a new value that includes the interest amount. Let’s write a main program to test this: def test(): amount = rate = addInterest(amount, rate) print(amount) Python Programming, 2/e

338 Functions that Modify Parameters
We hope that that the 5% will be added to the amount, returning 1050. >>> test() 1000 What went wrong? Nothing! Python Programming, 2/e

339 Functions that Modify Parameters
The first two lines of the test function create two local variables called amount and rate which are given the initial values of 1000 and 0.05, respectively. def addInterest(balance, rate): newBalance = balance * (1 + rate) balance = newBalance def test(): amount = 1000 rate = 0.05 addInterest(amount, rate) print(amount) Python Programming, 2/e

340 Functions that Modify Parameters
Control then transfers to the addInterest function. The formal parameters balance and rate are assigned the values of the actual parameters amount and rate. Even though rate appears in both, they are separate variables (because of scope rules). def addInterest(balance, rate): newBalance = balance * (1 + rate) balance = newBalance def test(): amount = 1000 rate = 0.05 addInterest(amount, rate) print(amount) Python Programming, 2/e

341 Functions that Modify Parameters
The assignment of the parameters causes the variables balance and rate in addInterest to refer to the values of the actual parameters! def addInterest(balance, rate): newBalance = balance*(1 + rate) balance = newBalance def test(): amount = 1000 rate = 0.05 addInterest(amount, rate) print(amount) Python Programming, 2/e

342 Functions that Modify Parameters
Python Programming, 2/e

343 Functions that Modify Parameters
Executing the first line of addInterest creates a new variable, newBalance. balance is then assigned the value of newBalance. def addInterest(balance, rate): newBalance = balance * (1 + rate) balance = newBalance def test(): amount = 1000 rate = 0.05 addInterest(amount, rate) print(amount) Python Programming, 2/e

344 Functions that Modify Parameters
balance now refers to the same value as newBalance, but this had no effect on amount in the test function. def addInterest(balance, rate): newBalance = balance * (1 + rate) balance = newBalance def test(): amount = 1000 rate = 0.05 addInterest(amount, rate) print (amount) Python Programming, 2/e

345 Functions that Modify Parameters
Python Programming, 2/e

346 Functions that Modify Parameters
Execution of addInterest has completed and control returns to test. The local variables, including the parameters, in addInterest go away, but amount and rate in the test function still refer to their initial values! def addInterest(balance, rate): newBalance = balance * (1 + rate) balance = newBalance def test(): amount = 1000 rate = 0.05 addInterest(amount, rate) print(amount) Python Programming, 2/e

347 Functions that Modify Parameters
To summarize: the formal parameters of a function only receive the values of the actual parameters. The function does not have access to the variable that holds the actual parameter. Python is said to pass all parameters by value. Python Programming, 2/e

348 Functions that Modify Parameters
Some programming languages (C++, Ada, and many more) do allow variables themselves to be sent as parameters to a function. This mechanism is said to pass parameters by reference. When a new value is assigned to the formal parameter, the value of the variable in the calling program actually changes. Python Programming, 2/e

349 Functions that Modify Parameters
Since Python doesn’t have this capability, one alternative would be to change the addInterest function so that it returns the newBalance. Python Programming, 2/e

350 Functions that Modify Parameters
def addInterest(balance, rate): newBalance = balance * (1 + rate) return newBalance def test(): amount = 1000 rate = 0.05 amount = addInterest(amount, rate) print(amount) test() Python Programming, 2/e

351 Functions that Modify Parameters
Instead of looking at a single account, say we are writing a program for a bank that deals with many accounts. We could store the account balances in a list, then add the accrued interest to each of the balances in the list. We could update the first balance in the list with code like: balances[0] = balances[0] * (1 + rate) Python Programming, 2/e

352 Functions that Modify Parameters
This code says, “multiply the value in the 0th position of the list by (1 + rate) and store the result back into the 0th position of the list.” A more general way to do this would be with a loop that goes through positions 0, 1, …, length – 1. Python Programming, 2/e

353 Functions that Modify Parameters
# addinterest3.py # Illustrates modification of a mutable parameter (a list). def addInterest(balances, rate): for i in range(len(balances)): balances[i] = balances[i] * (1+rate) def test(): amounts = [1000, 2200, 800, 360] rate = 0.05 addInterest(amounts, 0.05) print(amounts) test() Python Programming, 2/e

354 Functions that Modify Parameters
Remember, our original code had these values: [1000, 2200, 800, 360] The program returns: [1050.0, , 840.0, 378.0] What happened? Python passes parameters by value, but it looks like amounts has been changed! Python Programming, 2/e

355 Functions that Modify Parameters
The first two lines of test create the variables amounts and rate. The value of the variable amounts is a list object that contains four int values. def addInterest(balances, rate): for i in range(len(balances)): balances[i] = balances[i] * (1+rate) def test(): amounts = [1000, 2200, 800, 360] rate = 0.05 addInterest(amounts, 0.05) print(amounts) Python Programming, 2/e

356 Functions that Modify Parameters
Python Programming, 2/e

357 Functions that Modify Parameters
Next, addInterest executes. The loop goes through each index in the range 0, 1, …, length –1 and updates that value in balances. def addInterest(balances, rate): for i in range(len(balances)): balances[i] = balances[i] * (1+rate) def test(): amounts = [1000, 2200, 800, 360] rate = 0.05 addInterest(amounts, 0.05) print(amounts) Python Programming, 2/e

358 Functions that Modify Parameters
Python Programming, 2/e

359 Functions that Modify Parameters
In the diagram the old values are left hanging around to emphasize that the numbers in the boxes have not changed, but the new values were created and assigned into the list. The old values will be destroyed during garbage collection. def addInterest(balances, rate): for i in range(len(balances)): balances[i] = balances[i] * (1+rate) def test(): amounts = [1000, 2200, 800, 360] rate = 0.05 addInterest(amounts, 0.05) print amounts Python Programming, 2/e

360 Functions that Modify Parameters
When addInterest terminates, the list stored in amounts now contains the new values. The variable amounts wasn’t changed (it’s still a list), but the state of that list has changed, and this change is visible to the calling program. Python Programming, 2/e

361 Functions that Modify Parameters
Parameters are always passed by value. However, if the value of the variable is a mutable object (like a list of graphics object), then changes to the state of the object will be visible to the calling program. This situation is another example of the aliasing issue discussed in Chapter 4! Python Programming, 2/e

362 Functions and Program Structure
So far, functions have been used as a mechanism for reducing code duplication. Another reason to use functions is to make your programs more modular. As the algorithms you design get increasingly complex, it gets more and more difficult to make sense out of the programs. Python Programming, 2/e

363 Functions and Program Structure
One way to deal with this complexity is to break an algorithm down into smaller subprograms, each of which makes sense on its own. This topic will be discussed in more detail in Chapter 9. Python Programming, 2/e

364 Functions and Program Structure
def main(): # Introduction print("This program plots the growth of a 10 year investment.") # Get principal and interest rate principal = eval(input("Enter the initial principal: ")) apr = eval(input("Enter the annualized interest rate: ")) # Create a graphics window with labels on left edge win = GraphWin("Investment Growth Chart", 320, 240) win.setBackground("white") win.setCoords(-1.75,-200, 11.5, 10400) Text(Point(-1, 0), ' 0.0K').draw(win) Text(Point(-1, 2500), ' 2.5K').draw(win) Text(Point(-1, 5000), ' 5.0K').draw(win) Text(Point(-1, 7500), ' 7.5k').draw(win) Text(Point(-1, 10000), '10.0K').draw(win) # Draw bar for initial principal drawBar(win, 0, principal) # Draw a bar for each subsequent year for year in range(1, 11): principal = principal * (1 + apr) drawBar(win, year, principal) input("Press <Enter> to quit.") win.close() Python Programming, 2/e

365 Functions and Program Structure
We can make this program more readable by moving the middle eight lines that create the window where the chart will be drawn into a value returning function. Python Programming, 2/e

366 Functions and Program Structure
def createLabeledWindow(): window = GraphWin("Investment Growth Chart", 320, 240) window.setBackground("white") window.setCoords(-1.75,-200, 11.5, 10400) Text(Point(-1, 0), ' 0.0K').draw(window) Text(Point(-1, 2500), ' 2.5K').draw(window) Text(Point(-1, 5000), ' 5.0K').draw(window) Text(Point(-1, 7500), ' 7.5k').draw(window) Text(Point(-1, 10000), '10.0K').draw(window) return window def main(): print("This program plots the growth of a 10 year investment.") principal = eval(input("Enter the initial principal: ")) apr = eval(input("Enter the annualized interest rate: ")) win = createLabeledWindow() drawBar(win, 0, principal) for year in range(1, 11): principal = principal * (1 + apr) drawBar(win, year, principal) input("Press <Enter> to quit.") win.close() Python Programming, 2/e

367 Python Programming: An Introduction to Computer Science
Chapter 7 Decision Structures Python Programming, 2/e

368 Objectives To understand the programming pattern simple decision and its implementation using a Python if statement. To understand the programming pattern two-way decision and its implementation using a Python if-else statement. Python Programming, 2/e

369 Objectives (cont.) To understand the programming pattern multi-way decision and its implementation using a Python if-elif-else statement. To understand the idea of exception handling and be able to write simple exception handling code that catches standard Python run-time errors. Python Programming, 2/e

370 Objectives (cont.) To understand the concept of Boolean expressions and the bool data type. To be able to read, write, and implement algorithms that employ decision structures, including those that employ sequences of decisions and nested decision structures. Python Programming, 2/e

371 Simple Decisions So far, we’ve viewed programs as sequences of instructions that are followed one after the other. While this is a fundamental programming concept, it is not sufficient in itself to solve every problem. We need to be able to alter the sequential flow of a program to suit a particular situation. Python Programming, 2/e Python Programming, 1/e

372 Simple Decisions Control structures allow us to alter this sequential program flow. In this chapter, we’ll learn about decision structures, which are statements that allow a program to execute different sequences of instructions for different cases, allowing the program to “choose” an appropriate course of action. Python Programming, 2/e

373 Example: Temperature Warnings
Let’s return to our Celsius to Fahrenheit temperature conversion program from Chapter 2. # convert.py # A program to convert Celsius temps to Fahrenheit # by: Susan Computewell def main(): celsius = eval(input("What is the Celsius temperature? ")) fahrenheit = 9/5 * celsius + 32 print("The temperature is", fahrenheit, "degrees Fahrenheit.") main() Python Programming, 2/e

374 Example: Temperature Warnings
Let’s say we want to modify that program to print a warning when the weather is extreme. Any temperature over 90 degrees Fahrenheit and lower than 30 degrees Fahrenheit will cause a hot and cold weather warning, respectively. Python Programming, 2/e

375 Example: Temperature Warnings
Input the temperature in degrees Celsius (call it celsius) Calculate fahrenheit as 9/5 celsius + 32 Output fahrenheit If fahrenheit > print a heat warning If fahrenheit > print a cold warning Python Programming, 2/e

376 Example: Temperature Warnings
This new algorithm has two decisions at the end. The indentation indicates that a step should be performed only if the condition listed in the previous line is true. Python Programming, 2/e

377 Example: Temperature Warnings
Python Programming, 2/e

378 Example: Temperature Warnings
# convert2.py # A program to convert Celsius temps to Fahrenheit. # This version issues heat and cold warnings. def main(): celsius = eval(input("What is the Celsius temperature? ")) fahrenheit = 9 / 5 * celsius + 32 print("The temperature is", fahrenheit, "degrees fahrenheit.") if fahrenheit >= 90: print("It's really hot out there, be careful!") if fahrenheit <= 30: print("Brrrrr. Be sure to dress warmly") main() Python Programming, 2/e

379 Example: Temperature Warnings
The Python if statement is used to implement the decision. if <condition>: <body> The body is a sequence of one or more statements indented under the if heading. Python Programming, 2/e

380 Example: Temperature Warnings
The semantics of the if should be clear. First, the condition in the heading is evaluated. If the condition is true, the sequence of statements in the body is executed, and then control passes to the next statement in the program. If the condition is false, the statements in the body are skipped, and control passes to the next statement in the program. Python Programming, 2/e

381 Example: Temperature Warnings
Python Programming, 2/e

382 Example: Temperature Warnings
The body of the if either executes or not depending on the condition. In any case, control then passes to the next statement after the if. This is a one-way or simple decision. Python Programming, 2/e

383 Forming Simple Conditions
What does a condition look like? At this point, let’s use simple comparisons. <expr> <relop> <expr> <relop> is short for relational operator Python Programming, 2/e

384 Forming Simple Conditions
Python Mathematics Meaning < Less than <= Less than or equal to == = Equal to >= Greater than or equal to > Greater than != Not equal to Python Programming, 2/e

385 Forming Simple Conditions
Notice the use of == for equality. Since Python uses = to indicate assignment, a different symbol is required for the concept of equality. A common mistake is using = in conditions! Python Programming, 2/e

386 Forming Simple Conditions
Conditions may compare either numbers or strings. When comparing strings, the ordering is lexigraphic, meaning that the strings are sorted based on the underlying Unicode. Because of this, all upper-case letters come before lower-case letters. (“Bbbb” comes before “aaaa”) Python Programming, 2/e

387 Forming Simple Conditions
Conditions are based on Boolean expressions, named for the English mathematician George Boole. When a Boolean expression is evaluated, it produces either a value of true (meaning the condition holds), or it produces false (it does not hold). Some computer languages use 1 and 0 to represent “true” and “false”. Python Programming, 2/e

388 Forming Simple Conditions
Boolean conditions are of type bool and the Boolean values of true and false are represented by the literals True and False. >>> 3 < 4 True >>> 3 * 4 < 3 + 4 False >>> "hello" == "hello" >>> "Hello" < "hello" Python Programming, 2/e

389 Example: Conditional Program Execution
There are several ways of running Python programs. Some modules are designed to be run directly. These are referred to as programs or scripts. Others are made to be imported and used by other programs. These are referred to as libraries. Sometimes we want to create a hybrid that can be used both as a stand-alone program and as a library. Python Programming, 2/e

390 Example: Conditional Program Execution
When we want to start a program once it’s loaded, we include the line main() at the bottom of the code. Since Python evaluates the lines of the program during the import process, our current programs also run when they are imported into an interactive Python session or into another Python program. Python Programming, 2/e

391 Example: Conditional Program Execution
Generally, when we import a module, we don’t want it to execute! In a program that can be either run stand-alone or loaded as a library, the call to main at the bottom should be made conditional, e.g. if <condition>: main() Python Programming, 2/e

392 Example: Conditional Program Execution
Whenever a module is imported, Python creates a special variable in the module called __name__ to be the name of the imported module. Example: >>> import math >>> math.__name__ 'math' Python Programming, 2/e

393 Example: Conditional Program Execution
When imported, the __name__ variable inside the math module is assigned the string ‘math’. When Python code is run directly and not imported, the value of __name__ is ‘__main__’. E.g.: >>> __name__ '__main__' Python Programming, 2/e

394 Example: Conditional Program Execution
To recap: if a module is imported, the code in the module will see a variable called __name__ whose value is the name of the module. When a file is run directly, the code will see the value ‘__main__’. We can change the final lines of our programs to: if __name__ == '__main__': main() Virtually every Python module ends this way! Python Programming, 2/e

395 Two-Way Decisions Consider the quadratic program as we left it.
# quadratic.py # A program that computes the real roots of a quadratic equation. # Note: This program crashes if the equation has no real roots. import math def main(): print("This program finds the real solutions to a quadratic") a, b, c = eval(input("\nPlease enter the coefficients (a, b, c): ")) discRoot = math.sqrt(b * b - 4 * a * c) root1 = (-b + discRoot) / (2 * a) root2 = (-b - discRoot) / (2 * a) print("\nThe solutions are:", root1, root2) main() Python Programming, 2/e

396 Two-Way Decisions As per the comment, when b2-4ac < 0, the program crashes. This program finds the real solutions to a quadratic Please enter the coefficients (a, b, c): 1,1,2 Traceback (most recent call last): File "C:\Documents and Settings\Terry\My Documents\Teaching\W04\CS 120\Textbook\code\chapter3\quadratic.py", line 21, in -toplevel- main() File "C:\Documents and Settings\Terry\My Documents\Teaching\W04\CS 120\Textbook\code\chapter3\quadratic.py", line 14, in main discRoot = math.sqrt(b * b - 4 * a * c) ValueError: math domain error Python Programming, 2/e

397 Two-Way Decisions We can check for this situation. Here’s our first attempt. # quadratic2.py # A program that computes the real roots of a quadratic equation. # Bad version using a simple if to avoid program crash import math def main(): print("This program finds the real solutions to a quadratic\n") a, b, c = eval(input("Please enter the coefficients (a, b, c): ")) discrim = b * b - 4 * a * c if discrim >= 0: discRoot = math.sqrt(discrim) root1 = (-b + discRoot) / (2 * a) root2 = (-b - discRoot) / (2 * a) print("\nThe solutions are:", root1, root2) Python Programming, 2/e

398 Two-Way Decisions We first calculate the discriminant (b2-4ac) and then check to make sure it’s nonnegative. If it is, the program proceeds and we calculate the roots. Look carefully at the program. What’s wrong with it? Hint: What happens when there are no real roots? Python Programming, 2/e

399 Two-Way Decisions This program finds the real solutions to a quadratic Please enter the coefficients (a, b, c): 1,1,1 >>> This is almost worse than the version that crashes, because we don’t know what went wrong! Python Programming, 2/e

400 Two-Way Decisions We could add another if to the end: if discrim < 0: print("The equation has no real roots!" ) This works, but feels wrong. We have two decisions, with mutually exclusive outcomes (if discrim >= 0 then discrim < 0 must be false, and vice versa). Python Programming, 2/e

401 Two-Way Decisions Python Programming, 2/e

402 Two-Way Decisions In Python, a two-way decision can be implemented by attaching an else clause onto an if clause. This is called an if-else statement: if <condition>: <statements> else: <statements> Python Programming, 2/e

403 Two-Way Decisions When Python first encounters this structure, it first evaluates the condition. If the condition is true, the statements under the if are executed. If the condition is false, the statements under the else are executed. In either case, the statements following the if-else are executed after either set of statements are executed. Python Programming, 2/e

404 Two-Way Decisions Python Programming, 2/e # quadratic3.py
# A program that computes the real roots of a quadratic equation. # Illustrates use of a two-way decision import math def main(): print "This program finds the real solutions to a quadratic\n" a, b, c = eval(input("Please enter the coefficients (a, b, c): ")) discrim = b * b - 4 * a * c if discrim < 0: print("\nThe equation has no real roots!") else: discRoot = math.sqrt(b * b - 4 * a * c) root1 = (-b + discRoot) / (2 * a) root2 = (-b - discRoot) / (2 * a) print ("\nThe solutions are:", root1, root2 ) main() Python Programming, 2/e

405 Two-Way Decisions >>>
This program finds the real solutions to a quadratic Please enter the coefficients (a, b, c): 1,1,2 The equation has no real roots! Please enter the coefficients (a, b, c): 2, 5, 2 The solutions are: Python Programming, 2/e

406 Multi-Way Decisions The newest program is great, but it still has some quirks! This program finds the real solutions to a quadratic Please enter the coefficients (a, b, c): 1,2,1 The solutions are: Python Programming, 2/e

407 Multi-Way Decisions While correct, this method might be confusing for some people. It looks like it has mistakenly printed the same number twice! Double roots occur when the discriminant is exactly 0, and then the roots are –b/2a. It looks like we need a three-way decision! Python Programming, 2/e

408 Multi-Way Decisions Check the value of discrim when < 0: handle the case of no roots when = 0: handle the case of a double root when > 0: handle the case of two distinct roots We can do this with two if-else statements, one inside the other. Putting one compound statement inside of another is called nesting. Python Programming, 2/e

409 Multi-Way Decisions if discrim < 0:
print("Equation has no real roots") else: if discrim == 0: root = -b / (2 * a) print("There is a double root at", root) # Do stuff for two roots Python Programming, 2/e

410 Multi-Way Decisions Python Programming, 2/e

411 Multi-Way Decisions Imagine if we needed to make a five-way decision using nesting. The if-else statements would be nested four levels deep! There is a construct in Python that achieves this, combining an else followed immediately by an if into a single elif. Python Programming, 2/e

412 Multi-Way Decisions if <condition1>: <case1 statements> elif <condition2>: <case2 statements> elif <condition3>: <case3 statements> … else: <default statements> Python Programming, 2/e

413 Multi-Way Decisions This form sets of any number of mutually exclusive code blocks. Python evaluates each condition in turn looking for the first one that is true. If a true condition is found, the statements indented under that condition are executed, and control passes to the next statement after the entire if-elif-else. If none are true, the statements under else are performed. Python Programming, 2/e

414 Multi-Way Decisions The else is optional. If there is no else, it’s possible no indented block would be executed. Python Programming, 2/e

415 Multi-Way Decisions Python Programming, 2/e # quadratic4.py
# Illustrates use of a multi-way decision import math def main(): print("This program finds the real solutions to a quadratic\n") a, b, c = eval(input("Please enter the coefficients (a, b, c): ")) discrim = b * b - 4 * a * c if discrim < 0: print("\nThe equation has no real roots!") elif discrim == 0: root = -b / (2 * a) print("\nThere is a double root at", root) else: discRoot = math.sqrt(b * b - 4 * a * c) root1 = (-b + discRoot) / (2 * a) root2 = (-b - discRoot) / (2 * a) print("\nThe solutions are:", root1, root2 ) Python Programming, 2/e

416 Exception Handling In the quadratic program we used decision structures to avoid taking the square root of a negative number, thus avoiding a run-time error. This is true for many programs: decision structures are used to protect against rare but possible errors. Python Programming, 2/e

417 Exception Handling In the quadratic example, we checked the data before calling sqrt. Sometimes functions will check for errors and return a special value to indicate the operation was unsuccessful. E.g., a different square root operation might return a –1 to indicate an error (since square roots are never negative, we know this value will be unique). Python Programming, 2/e

418 Exception Handling discRt = otherSqrt(b*b - 4*a*c) if discRt < 0: print("No real roots.“) else: Sometimes programs get so many checks for special cases that the algorithm becomes hard to follow. Programming language designers have come up with a mechanism to handle exception handling to solve this design problem. Python Programming, 2/e

419 Exception Handling The programmer can write code that catches and deals with errors that arise while the program is running, i.e., “Do these steps, and if any problem crops up, handle it this way.” This approach obviates the need to do explicit checking at each step in the algorithm. Python Programming, 2/e

420 Exception Handling # quadratic5.py
# A program that computes the real roots of a quadratic equation. # Illustrates exception handling to avoid crash on bad inputs import math def main(): print("This program finds the real solutions to a quadratic\n") try: a, b, c = eval(input("Please enter the coefficients (a, b, c): ")) discRoot = math.sqrt(b * b - 4 * a * c) root1 = (-b + discRoot) / (2 * a) root2 = (-b - discRoot) / (2 * a) print("\nThe solutions are:", root1, root2) except ValueError: print("\nNo real roots") Python Programming, 2/e

421 Exception Handling The try statement has the following form: try: <body> except <ErrorType>: <handler> When Python encounters a try statement, it attempts to execute the statements inside the body. If there is no error, control passes to the next statement after the try…except. Python Programming, 2/e

422 Exception Handling If an error occurs while executing the body, Python looks for an except clause with a matching error type. If one is found, the handler code is executed. The original program generated this error with a negative discriminant: Traceback (most recent call last): File "C:\Documents and Settings\Terry\My Documents\Teaching\W04\CS120\Textbook\code\chapter3\quadratic.py", line 21, in -toplevel- main() File "C:\Documents and Settings\Terry\My Documents\Teaching\W04\CS 120\Textbook\code\chapter3\quadratic.py", line 14, in main discRoot = math.sqrt(b * b - 4 * a * c) ValueError: math domain error Python Programming, 2/e

423 Exception Handling The last line, “ValueError: math domain error”, indicates the specific type of error. Here’s the new code in action: This program finds the real solutions to a quadratic Please enter the coefficients (a, b, c): 1, 1, 1 No real roots Instead of crashing, the exception handler prints a message indicating that there are no real roots. Python Programming, 2/e

424 Exception Handling The try…except can be used to catch any kind of error and provide for a graceful exit. In the case of the quadratic program, other possible errors include not entering the right number of parameters (“unpack tuple of wrong size”), entering an identifier instead of a number (NameError), entering an invalid Python expression (TypeError). A single try statement can have multiple except clauses. Python Programming, 2/e

425 Exception Handling Python Programming, 2/e # quadratic6.py import math
def main(): print("This program finds the real solutions to a quadratic\n") try: a, b, c = eval(input("Please enter the coefficients (a, b, c): ")) discRoot = math.sqrt(b * b - 4 * a * c) root1 = (-b + discRoot) / (2 * a) root2 = (-b - discRoot) / (2 * a) print("\nThe solutions are:", root1, root2 ) except ValueError as excObj: if str(excObj) == "math domain error": print("No Real Roots") else: print("You didn't give me the right number of coefficients.") except NameError: print("\nYou didn't enter three numbers.") except TypeError: print("\nYour inputs were not all numbers.") except SyntaxError: print("\nYour input was not in the correct form. Missing comma?") except: print("\nSomething went wrong, sorry!") main() Python Programming, 2/e

426 Exception Handling The multiple excepts act like elifs. If an error occurs, Python will try each except looking for one that matches the type of error. The bare except at the bottom acts like an else and catches any errors without a specific match. If there was no bare except at the end and none of the except clauses match, the program would still crash and report an error. Python Programming, 2/e

427 Exception Handling Exceptions themselves are a type of object.
If you follow the error type with an identifier in an except clause, Python will assign that identifier the actual exception object. Python Programming, 2/e

428 Study in Design: Max of Three
Now that we have decision structures, we can solve more complicated programming problems. The negative is that writing these programs becomes harder! Suppose we need an algorithm to find the largest of three numbers. Python Programming, 2/e

429 Study in Design: Max of Three
def main(): x1, x2, x3 = eval(input("Please enter three values: ")) # missing code sets max to the value of the largest print("The largest value is", max) Python Programming, 2/e

430 Strategy 1: Compare Each to All
This looks like a three-way decision, where we need to execute one of the following: max = x1 max = x2 max = x3 All we need to do now is preface each one of these with the right condition! Python Programming, 2/e

431 Strategy 1: Compare Each to All
Let’s look at the case where x1 is the largest. if x1 >= x2 >= x3: max = x1 Is this syntactically correct? Many languages would not allow this compound condition Python does allow it, though. It’s equivalent to x1 ≥ x2 ≥ x3. Python Programming, 2/e

432 Strategy 1: Compare Each to All
Whenever you write a decision, there are two crucial questions: When the condition is true, is executing the body of the decision the right action to take? x1 is at least as large as x2 and x3, so assigning max to x1 is OK. Always pay attention to borderline values!! Python Programming, 2/e

433 Strategy 1: Compare Each to All
Secondly, ask the converse of the first question, namely, are we certain that this condition is true in all cases where x1 is the max? Suppose the values are 5, 2, and 4. Clearly, x1 is the largest, but does x1 ≥ x2 ≥ x3 hold? We don’t really care about the relative ordering of x2 and x3, so we can make two separate tests: x1 >= x2 and x1 >= x3. Python Programming, 2/e

434 Strategy 1: Compare Each to All
We can separate these conditions with and! if x1 >= x2 and x1 >= x3: max = x1 elif x2 >= x1 and x2 >= x3: max = x2 else: max = x3 We’re comparing each possible value against all the others to determine which one is largest. Python Programming, 2/e

435 Strategy 1: Compare Each to All
What would happen if we were trying to find the max of five values? We would need four Boolean expressions, each consisting of four conditions anded together. Yuck! Python Programming, 2/e

436 Strategy 2: Decision Tree
We can avoid the redundant tests of the previous algorithm using a decision tree approach. Suppose we start with x1 >= x2. This knocks either x1 or x2 out of contention to be the max. If the conidition is true, we need to see which is larger, x1 or x3. Python Programming, 2/e

437 Strategy 2: Decision Tree
Python Programming, 2/e

438 Strategy 2: Decision Tree
if x1 >= x2: if x1 >= x3: max = x1 else: max = x3 else: if x2 >= x3: max = x2 else max = x3 Python Programming, 2/e

439 Strategy 2: Decision Tree
This approach makes exactly two comparisons, regardless of the ordering of the original three variables. However, this approach is more complicated than the first. To find the max of four values you’d need if-elses nested three levels deep with eight assignment statements. Python Programming, 2/e

440 Strategy 3: Sequential Processing
How would you solve the problem? You could probably look at three numbers and just know which is the largest. But what if you were given a list of a hundred numbers? One strategy is to scan through the list looking for a big number. When one is found, mark it, and continue looking. If you find a larger value, mark it, erase the previous mark, and continue looking. Python Programming, 2/e

441 Strategy 3: Sequential Processing
Python Programming, 2/e

442 Strategy 3: Sequential Processing
This idea can easily be translated into Python. max = x1 if x2 > max: max = x2 if x3 > max: max = x3 Python Programming, 2/e

443 Strategy 3: Sequential Programming
This process is repetitive and lends itself to using a loop. We prompt the user for a number, we compare it to our current max, if it is larger, we update the max value, repeat. Python Programming, 2/e

444 Strategy 3: Sequential Programming
# maxn.py # Finds the maximum of a series of numbers def main(): n = eval(input("How many numbers are there? ")) # Set max to be the first value max = eval(input("Enter a number >> ")) # Now compare the n-1 successive values for i in range(n-1): x = eval(input("Enter a number >> ")) if x > max: max = x print("The largest value is", max) Python Programming, 2/e

445 Strategy 4: Use Python Python has a built-in function called max that returns the largest of its parameters. def main(): x1, x2, x3 = eval(input("Please enter three values: ")) print("The largest value is", max(x1, x2, x3)) Python Programming, 2/e

446 Some Lessons There’s usually more than one way to solve a problem.
Don’t rush to code the first idea that pops out of your head. Think about the design and ask if there’s a better way to approach the problem. Your first task is to find a correct algorithm. After that, strive for clarity, simplicity, efficiency, scalability, and elegance. Python Programming, 2/e

447 Some Lessons Be the computer.
One of the best ways to formulate an algorithm is to ask yourself how you would solve the problem. This straightforward approach is often simple, clear, and efficient enough. Python Programming, 2/e

448 Some Lessons Generality is good.
Consideration of a more general problem can lead to a better solution for a special case. If the max of n program is just as easy to write as the max of three, write the more general program because it’s more likely to be useful in other situations. Python Programming, 2/e

449 Some Lessons Don’t reinvent the wheel.
If the problem you’re trying to solve is one that lots of other people have encountered, find out if there’s already a solution for it! As you learn to program, designing programs from scratch is a great experience! Truly expert programmers know when to borrow. Python Programming, 2/e

450 Python Programming: An Introduction To Computer Science
Chapter 8 Loop Structures and Booleans Python Programming, 2/e

451 Objectives To understand the concepts of definite and indefinite loops as they are realized in the Python for and while statements. To understand the programming patterns interactive loop and sentinel loop and their implementations using a Python while statement. Python Programming, 2/e

452 Objectives To understand the programming pattern end-of-file loop and ways of implementing such loops in Python. To be able to design and implement solutions to problems involving loop patterns including nested loop structures. Python Programming, 2/e

453 Objectives To understand the basic ideas of Boolean algebra and be able to analyze and write Boolean expressions involving Boolean operators. Python Programming, 2/e

454 For Loops: A Quick Review
The for statement allows us to iterate through a sequence of values. for <var> in <sequence>: <body> The loop index variable var takes on each successive value in the sequence, and the statements in the body of the loop are executed once for each value. Python Programming, 2/e Python Programming, 1/e

455 For Loops: A Quick Review
Suppose we want to write a program that can compute the average of a series of numbers entered by the user. To make the program general, it should work with any size set of numbers. We don’t need to keep track of each number entered, we only need know the running sum and how many numbers have been added. Python Programming, 2/e

456 For Loops: A Quick Review
We’ve run into some of these things before! A series of numbers could be handled by some sort of loop. If there are n numbers, the loop should execute n times. We need a running sum. This will use an accumulator. Python Programming, 2/e

457 For Loops: A Quick Review
Input the count of the numbers, n Initialize sum to 0 Loop n times Input a number, x Add x to sum Output average as sum/n Python Programming, 2/e

458 For Loops: A Quick Review
# average1.py # A program to average a set of numbers # Illustrates counted loop with accumulator def main(): n = eval(input("How many numbers do you have? ")) sum = 0.0 for i in range(n): x = eval(input("Enter a number >> ")) sum = sum + x print("\nThe average of the numbers is", sum / n) Note that sum is initialized to 0.0 so that sum/n returns a float! Python Programming, 2/e

459 For Loops: A Quick Review
How many numbers do you have? 5 Enter a number >> 32 Enter a number >> 45 Enter a number >> 34 Enter a number >> 76 The average of the numbers is 46.4 Python Programming, 2/e

460 Indefinite Loops That last program got the job done, but you need to know ahead of time how many numbers you’ll be dealing with. What we need is a way for the computer to take care of counting how many numbers there are. The for loop is a definite loop, meaning that the number of iterations is determined when the loop starts. Python Programming, 2/e

461 Indefinite Loops We can’t use a definite loop unless we know the number of iterations ahead of time. We can’t know how many iterations we need until all the numbers have been entered. We need another tool! The indefinite or conditional loop keeps iterating until certain conditions are met. Python Programming, 2/e

462 Indefinite Loops while <condition>: <body>
condition is a Boolean expression, just like in if statements. The body is a sequence of one or more statements. Semantically, the body of the loop executes repeatedly as long as the condition remains true. When the condition is false, the loop terminates. Python Programming, 2/e

463 Indefinite Loops The condition is tested at the top of the loop. This is known as a pre-test loop. If the condition is initially false, the loop body will not execute at all. Python Programming, 2/e

464 Indefinite Loop Here’s an example of a while loop that counts from 0 to 10: i = 0 while i <= 10: print(i) i = i + 1 The code has the same output as this for loop: for i in range(11): print(i) Python Programming, 2/e

465 Indefinite Loop The while loop requires us to manage the loop variable i by initializing it to 0 before the loop and incrementing it at the bottom of the body. In the for loop this is handled automatically. Python Programming, 2/e

466 Indefinite Loop The while statement is simple, but yet powerful and dangerous – they are a common source of program errors. i = 0 while i <= 10: print(i) What happens with this code? Python Programming, 2/e

467 Indefinite Loop When Python gets to this loop, i is equal to 0, which is less than 10, so the body of the loop is executed, printing 0. Now control returns to the condition, and since i is still 0, the loop repeats, etc. This is an example of an infinite loop. Python Programming, 2/e

468 Indefinite Loop What should you do if you’re caught in an infinite loop? First, try pressing control-c If that doesn’t work, try control-alt-delete If that doesn’t work, push the reset button! Python Programming, 2/e

469 Interactive Loops One good use of the indefinite loop is to write interactive loops. Interactive loops allow a user to repeat certain portions of a program on demand. Remember how we said we needed a way for the computer to keep track of how many numbers had been entered? Let’s use another accumulator, called count. Python Programming, 2/e

470 Interactive Loops At each iteration of the loop, ask the user if there is more data to process. We need to preset it to “yes” to go through the loop the first time. set moredata to “yes” while moredata is “yes” get the next data item process the item ask user if there is moredata Python Programming, 2/e

471 Interactive Loops Combining the interactive loop pattern with accumulators for sum and count: initialize sum to 0.0 initialize count to 0 set moredata to “yes” while moredata is “yes” input a number, x add x to sum add 1 to count ask user if there is moredata output sum/count Python Programming, 2/e

472 Interactive Loops # average2.py # A program to average a set of numbers # Illustrates interactive loop with two accumulators def main(): moredata = "yes" sum = 0.0 count = 0 while moredata[0] == 'y': x = eval(input("Enter a number >> ")) sum = sum + x count = count + 1 moredata = input("Do you have more numbers (yes or no)? ") print("\nThe average of the numbers is", sum / count) Using string indexing (moredata[0]) allows us to accept “y”, “yes”, “yeah” to continue the loop Python Programming, 2/e

473 Interactive Loops Enter a number >> 32
Do you have more numbers (yes or no)? y Enter a number >> 45 Do you have more numbers (yes or no)? yes Enter a number >> 34 Do you have more numbers (yes or no)? yup Enter a number >> 76 Do you have more numbers (yes or no)? nah The average of the numbers is 46.4 Python Programming, 2/e

474 Sentinel Loops A sentinel loop continues to process data until reaching a special value that signals the end. This special value is called the sentinel. The sentinel must be distinguishable from the data since it is not processed as part of the data. Python Programming, 2/e

475 Sentinel Loops get the first data item while item is not the sentinel process the item get the next data item The first item is retrieved before the loop starts. This is sometimes called the priming read, since it gets the process started. If the first item is the sentinel, the loop terminates and no data is processed. Otherwise, the item is processed and the next one is read. Python Programming, 2/e

476 Sentinel Loops In our averaging example, assume we are averaging test scores. We can assume that there will be no score below 0, so a negative number will be the sentinel. Python Programming, 2/e

477 Sentinel Loops # average3.py # A program to average a set of numbers
# Illustrates sentinel loop using negative input as sentinel def main(): sum = 0.0 count = 0 x = eval(input("Enter a number (negative to quit) >> ")) while x >= 0: sum = sum + x count = count + 1 print("\nThe average of the numbers is", sum / count) Python Programming, 2/e

478 Sentinel Loops Enter a number (negative to quit) >> 32
The average of the numbers is 46.4 Python Programming, 2/e

479 Sentinel Loops This version provides the ease of use of the interactive loop without the hassle of typing ‘y’ all the time. There’s still a shortcoming – using this method we can’t average a set of positive and negative numbers. If we do this, our sentinel can no longer be a number. Python Programming, 2/e

480 Sentinel Loops We could input all the information as strings.
Valid input would be converted into numeric form. Use a character-based sentinel. We could use the empty string (“”)! Python Programming, 2/e

481 Sentinel Loops initialize sum to 0.0 initialize count to 0
input data item as a string, xStr while xStr is not empty convert xStr to a number, x add x to sum add 1 to count input next data item as a string, xStr Output sum / count Python Programming, 2/e

482 Sentinel Loops # average4.py # A program to average a set of numbers
# Illustrates sentinel loop using empty string as sentinel def main(): sum = 0.0 count = 0 xStr = input("Enter a number (<Enter> to quit) >> ") while xStr != "": x = eval(xStr) sum = sum + x count = count + 1 print("\nThe average of the numbers is", sum / count) Python Programming, 2/e

483 Sentinel Loops Enter a number (<Enter> to quit) >> 34
The average of the numbers is Python Programming, 2/e

484 File Loops The biggest disadvantage of our program at this point is that they are interactive. What happens if you make a typo on number 43 out of 50? A better solution for large data sets is to read the data from a file. Python Programming, 2/e

485 File Loops # average5.py # Computes the average of numbers listed in a file. def main(): fileName = input("What file are the numbers in? ") infile = open(fileName,'r') sum = 0.0 count = 0 for line in infile.readlines(): sum = sum + eval(line) count = count + 1 print("\nThe average of the numbers is", sum / count) Python Programming, 2/e

486 File Loops Many languages don’t have a mechanism for looping through a file like this. Rather, they use a sentinel! We could use readline in a loop to get the next line of the file. At the end of the file, readline returns an empty string, “” Python Programming, 2/e

487 File Loops line = infile.readline() while line != "" #process line line = infile.readline() Does this code correctly handle the case where there’s a blank line in the file? Yes. An empty line actually ends with the newline character, and readline includes the newline. “\n” != “” Python Programming, 2/e

488 File Loops # average6.py # Computes the average of numbers listed in a file. def main(): fileName = input("What file are the numbers in? ") infile = open(fileName,'r') sum = 0.0 count = 0 line = infile.readline() while line != "": sum = sum + eval(line) count = count + 1 print("\nThe average of the numbers is", sum / count) Python Programming, 2/e

489 Nested Loops In the last chapter we saw how we could nest if statements. We can also nest loops. Suppose we change our specification to allow any number of numbers on a line in the file (separated by commas), rather than one per line. Python Programming, 2/e

490 Nested Loops At the top level, we will use a file-processing loop that computes a running sum and count. sum = 0.0 count = 0 line = infile.readline() while line != "": #update sum and count for values in line print("\nThe average of the numbers is", sum/count) Python Programming, 2/e

491 Nested Loops In the next level in we need to update the sum and count in the body of the loop. Since each line of the file contains one or more numbers separated by commas, we can split the string into substrings, each of which represents a number. Then we need to loop through the substrings, convert each to a number, and add it to sum. We also need to update count. Python Programming, 2/e

492 Nested Loops for xStr in line.split(","): sum = sum + eval(xStr) count = count + 1 Notice that this for statement uses line, which is also the loop control variable for the outer loop. Python Programming, 2/e

493 Nested Loops # average7.py
# Computes the average of numbers listed in a file. # Works with multiple numbers on a line. import string def main(): fileName = input("What file are the numbers in? ") infile = open(fileName,'r') sum = 0.0 count = 0 line = infile.readline() while line != "": for xStr in line.split(","): sum = sum + eval(xStr) count = count + 1 print("\nThe average of the numbers is", sum / count) Python Programming, 2/e

494 Nested Loops The loop that processes the numbers in each line is indented inside of the file processing loop. The outer while loop iterates once for each line of the file. For each iteration of the outer loop, the inner for loop iterates as many times as there are numbers on the line. When the inner loop finishes, the next line of the file is read, and this process begins again. Python Programming, 2/e

495 Nested Loops Designing nested loops –
Design the outer loop without worrying about what goes inside Design what goes inside, ignoring the outer loop. Put the pieces together, preserving the nesting. Python Programming, 2/e

496 Computing with Booleans
if and while both use Boolean expressions. Boolean expressions evaluate to True or False. So far we’ve used Boolean expressions to compare two values, e.g. (while x >= 0) Python Programming, 2/e

497 Boolean Operators Sometimes our simple expressions do not seem expressive enough. Suppose you need to determine whether two points are in the same position – their x coordinates are equal and their y coordinates are equal. Python Programming, 2/e

498 Boolean Operators if p1.getX() == p2.getX(): if p1.getY() == p2.getY(): # points are the same else: # points are different else: # points are different Clearly, this is an awkward way to evaluate multiple Boolean expressions! Let’s check out the three Boolean operators and, or, and not. Python Programming, 2/e

499 Boolean Operators The Boolean operators and and or are used to combine two Boolean expressions and produce a Boolean result. <expr> and <expr> <expr> or <expr> Python Programming, 2/e

500 Boolean Operators The and of two expressions is true exactly when both of the expressions are true. We can represent this in a truth table. P Q P and Q T F Python Programming, 2/e

501 Boolean Expressions In the truth table, P and Q represent smaller Boolean expressions. Since each expression has two possible values, there are four possible combinations of values. The last column gives the value of P and Q. Python Programming, 2/e

502 Boolean Expressions The or of two expressions is true when either expression is true. P Q P or Q T F Python Programming, 2/e

503 Boolean Expressions The only time or is false is when both expressions are false. Also, note that or is true when both expressions are true. This isn’t how we normally use “or” in language. Python Programming, 2/e

504 Boolean Operators The not operator computes the opposite of a Boolean expression. not is a unary operator, meaning it operates on a single expression. P not P T F Python Programming, 2/e

505 Boolean Operators We can put these operators together to make arbitrarily complex Boolean expressions. The interpretation of the expressions relies on the precedence rules for the operators. Python Programming, 2/e

506 Boolean Operators Consider a or not b and c
How should this be evaluated? The order of precedence, from high to low, is not, and, or. This statement is equivalent to (a or ((not b) and c)) Since most people don’t memorize the the Boolean precedence rules, use parentheses to prevent confusion. Python Programming, 2/e

507 Boolean Operators To test for the co-location of two points, we could use an and. if p1.getX() == p2.getX() and p2.getY() == p1.getY(): # points are the same else: # points are different The entire condition will be true only when both of the simpler conditions are true. Python Programming, 2/e

508 Boolean Operators Say you’re writing a racquetball simulation. The game is over as soon as either player has scored 15 points. How can you represent that in a Boolean expression? scoreA == 15 or scoreB == 15 When either of the conditions becomes true, the entire expression is true. If neither condition is true, the expression is false. Python Programming, 2/e

509 Boolean Operators We want to construct a loop that continues as long as the game is not over. You can do this by taking the negation of the game-over condition as your loop condition! while not(scoreA == 15 or scoreB == 15): #continue playing Python Programming, 2/e

510 Boolean Operators Some racquetball players also use a shutout condition to end the game, where if one player has scored 7 points and the other person hasn’t scored yet, the game is over. while not(scoreA == 15 or scoreB == 15 or \ (scoreA == 7 and scoreB == 0) or (scoreB == 7 and scoreA == 0): #continue playing Python Programming, 2/e

511 Boolean Operators Let’s look at volleyball scoring. To win, a volleyball team needs to win by at least two points. In volleyball, a team wins at 15 points If the score is 15 – 14, play continues, just as it does for 21 – 20. (a >= 15 and a - b >= 2) or (b >= 15 and b - a >= 2) (a >= 15 or b >= 15) and abs(a - b) >= 2 Python Programming, 2/e

512 Boolean Algebra The ability to formulate, manipulate, and reason with Boolean expressions is an important skill. Boolean expressions obey certain algebraic laws called Boolean logic or Boolean algebra. Python Programming, 2/e

513 Boolean Algebra Algebra Boolean algebra a * 0 = 0 a and false == false
a and true == a a + 0 = a a or false == a and has properties similar to multiplication or has properties similar to addition 0 and 1 correspond to false and true, respectively. Python Programming, 2/e

514 Boolean Algebra Anything ored with true is true: a or true == true
Both and and or distribute: a or (b and c) == (a or b) and (a or c) a and (b or c) == (a and b) or (a and c) Double negatives cancel out: not(not a) == a DeMorgan’s laws: not(a or b) == (not a) and (not b) not(a and b) == (not a) or (not b) Python Programming, 2/e

515 Boolean Algebra We can use these rules to simplify our Boolean expressions. while not(scoreA == 15 or scoreB == 15): #continue playing This is saying something like “While it is not the case that player A has 15 or player B has 15, continue playing.” Applying DeMorgan’s law: while (not scoreA == 15) and (not scoreB == 15): #continue playing Python Programming, 2/e

516 Boolean Algebra This becomes: while scoreA != 15 and scoreB != # continue playing Isn’t this easier to understand? “While player A has not reached 15 and player B has not reached 15, continue playing.” Python Programming, 2/e

517 Boolean Algebra Sometimes it’s easier to figure out when a loop should stop, rather than when the loop should continue. In this case, write the loop termination condition and put a not in front of it. After a couple applications of DeMorgan’s law you are ready to go with a simpler but equivalent expression. Python Programming, 2/e

518 Other Common Structures
The if and while can be used to express every conceivable algorithm. For certain problems, an alternative structure can be convenient. Python Programming, 2/e

519 Post-Test Loop Say we want to write a program that is supposed to get a nonnegative number from the user. If the user types an incorrect input, the program asks for another value. This process continues until a valid value has been entered. This process is input validation. Python Programming, 2/e

520 Post-Test Loop repeat get a number from the user until number is >= 0 Python Programming, 2/e

521 Post-Test Loop When the condition test comes after the body of the loop it’s called a post-test loop. A post-test loop always executes the body of the code at least once. Python doesn’t have a built-in statement to do this, but we can do it with a slightly modified while loop. Python Programming, 2/e

522 Post-Test Loop We seed the loop condition so we’re guaranteed to execute the loop once. number = -1 while number < 0: number = eval(input("Enter a positive number: ")) By setting number to –1, we force the loop body to execute at least once. Python Programming, 2/e

523 Post-Test Loop Some programmers prefer to simulate a post-test loop by using the Python break statement. Executing break causes Python to immediately exit the enclosing loop. break is sometimes used to exit what looks like an infinite loop. Python Programming, 2/e

524 Post-Test Loop The same algorithm implemented with a break: while True: number = eval(input("Enter a positive number: ")) if x >= 0: break # Exit loop if number is valid A while loop continues as long as the expression evaluates to true. Since True always evaluates to true, it looks like an infinite loop! Python Programming, 2/e

525 Post-Test Loop When the value of x is nonnegative, the break statement executes, which terminates the loop. If the body of an if is only one line long, you can place it right after the :! Wouldn’t it be nice if the program gave a warning when the input was invalid? Python Programming, 2/e

526 Post-Test Loop In the while loop version, this is awkward: number = -1 while number < 0: number = eval(input("Enter a positive number: ")) if number < 0: print("The number you entered was not positive") We’re doing the validity check in two places! Python Programming, 2/e

527 Post-Test Loop Adding the warning to the break version only adds an else statement: while True: number = eval(input("Enter a positive number: ")) if x >= 0: break # Exit loop if number is valid else: print("The number you entered was not positive.") Python Programming, 2/e

528 Loop and a Half Stylistically, some programmers prefer the following approach: while True: number = eval(input("Enter a positive number: ")) if x >= 0: break # Loop exit print("The number you entered was not positive") Here the loop exit is in the middle of the loop body. This is what we mean by a loop and a half. Python Programming, 2/e

529 Loop and a Half The loop and a half is an elegant way to avoid the priming read in a sentinel loop. while True: get next data item if the item is the sentinel: break process the item This method is faithful to the idea of the sentinel loop, the sentinel value is not processed! Python Programming, 2/e

530 Loop and a Half Python Programming, 2/e

531 Loop and a Half To use or not use break. That is the question!
The use of break is mostly a matter of style and taste. Avoid using break often within loops, because the logic of a loop is hard to follow when there are multiple exits. Python Programming, 2/e

532 Boolean Expressions as Decisions
Boolean expressions can be used as control structures themselves. Suppose you’re writing a program that keeps going as long as the user enters a response that starts with ‘y’ (like our interactive loop). One way you could do it: while response[0] == "y" or response[0] == "Y": Python Programming, 2/e

533 Boolean Expressions as Decisions
Be careful! You can’t take shortcuts: while response[0] == "y" or "Y": Why doesn’t this work? Python has a bool type that internally uses 1 and 0 to represent True and False, respectively. The Python condition operators, like ==, always evaluate to a value of type bool. Python Programming, 2/e

534 Boolean Expressions as Decisions
However, Python will let you evaluate any built-in data type as a Boolean. For numbers (int, float, and long ints), zero is considered False, anything else is considered True. Python Programming, 2/e

535 Boolean Expressions as Decisions
False >>> bool(1) True >>> bool(32) >>> bool("Hello") >>> bool("") >>> bool([1,2,3]) >>> bool([]) Python Programming, 2/e

536 Boolean Expressions as Decisions
An empty sequence is interpreted as False while any non-empty sequence is taken to mean True. The Boolean operators have operational definitions that make them useful for other purposes. Python Programming, 2/e

537 Boolean Expressions as Decisions
Operator Operational definition x and y If x is false, return x. Otherwise, return y. x or y If x is true, return x. Otherwise, return y. not x If x is false, return True. Otherwise, return False. Python Programming, 2/e

538 Boolean Expressions as Decisions
Consider x and y. In order for this to be true, both x and y must be true. As soon as one of them is found to be false, we know the expression as a whole is false and we don’t need to finish evaluating the expression. So, if x is false, Python should return a false result, namely x. Python Programming, 2/e

539 Boolean Expressions as Decisions
If x is true, then whether the expression as a whole is true or false depends on y. By returning y, if y is true, then true is returned. If y is false, then false is returned. Python Programming, 2/e

540 Boolean Expressions as Decisions
These definitions show that Python’s Booleans are short-circuit operators, meaning that a true or false is returned as soon as the result is known. In an and where the first expression is false and in an or, where the first expression is true, Python will not evaluate the second expression. Python Programming, 2/e

541 Boolean Expressions as Decisions
response[0] == "y" or "Y“ The Boolean operator is combining two operations. Here’s an equivalent expression: (response[0] == "y") or ("Y") By the operational description of or, this expression returns either True, if response[0] equals “y”, or “Y”, both of which are interpreted by Python as true. Python Programming, 2/e

542 Boolean Expressions as Decisions
Sometimes we write programs that prompt for information but offer a default value obtained by simply pressing <Enter> Since the string used by ans can be treated as a Boolean, the code can be further simplified. Python Programming, 2/e

543 Boolean Expressions as Decisions
ans = input("What flavor fo you want [vanilla]: ") if ans: flavor = ans else: flavor = "vanilla" If the user just hits <Enter>, ans will be an empty string, which Python interprets as false. Python Programming, 2/e

544 Boolean Expressions as Decisions
We can code this even more succinctly! ans = input("What flavor fo you want [vanilla]: ") flavor = ans or "vanilla“ Remember, any non-empty answer is interpreted as True. This exercise could be boiled down into one line! flavor = input("What flavor do you want [vanilla]:” ) or "vanilla" Python Programming, 2/e

545 Boolean Expressions as Decisions
Again, if you understand this method, feel free to utilize it. Just make sure that if your code is tricky, that it’s well documented! Python Programming, 2/e

546 Python Programming: An Introduction to Computer Science
Chapter 9 Simulation and Design Python Programming, 2/e

547 Objectives To understand the potential applications of simulation as a way to solve real-world problems. To understand pseudorandom numbers and their application in Monte Carlo simulations. To understand and be able to apply top-down and spiral design techniques in writing complex programs. Python Programming, 2/e

548 Objectives To understand unit-testing and be able to apply this technique in the implementation and debugging of complex programming. Python Programming, 2/e

549 Simulating Racquetball
Simulation can solve real-world problems by modeling real-world processes to provide otherwise unobtainable information. Computer simulation is used to predict the weather, design aircraft, create special effects for movies, etc. Python Programming, 2/e

550 A Simulation Problem Denny Dibblebit often plays racquetball with players who are slightly better than he is. Denny usually loses his matches! Shouldn’t players who are a little better win a little more often? Susan suggests that they write a simulation to see if slight differences in ability can cause such large differences in scores. Python Programming, 2/e

551 Analysis and Specification
Racquetball is played between two players using a racquet to hit a ball in a four-walled court. One player starts the game by putting the ball in motion – serving. Players try to alternate hitting the ball to keep it in play, referred to as a rally. The rally ends when one player fails to hit a legal shot. Python Programming, 2/e

552 Analysis and Specification
The player who misses the shot loses the rally. If the loser is the player who served, service passes to the other player. If the server wins the rally, a point is awarded. Players can only score points during their own service. The first player to reach 15 points wins the game. Python Programming, 2/e

553 Analysis and Specification
In our simulation, the ability level of the players will be represented by the probability that the player wins the rally when he or she serves. Example: Players with a 0.60 probability win a point on 60% of their serves. The program will prompt the user to enter the service probability for both players and then simulate multiple games of racquetball. The program will then print a summary of the results. Python Programming, 2/e Python Programming, 1/e

554 Analysis and Specification
Input: The program prompts for and gets the service probabilities of players A and B. The program then prompts for and gets the number of games to be simulated. Python Programming, 2/e

555 Analysis and Specification
Output: The program will provide a series of initial prompts such as the following: What is the probability player A wins a serve? What is the probability that player B wins a server? How many games to simulate? The program then prints out a nicely formatted report showing the number of games simulated and the number of wins and the winning percentage for each player. Games simulated: 500 Wins for A: 268 (53.6%) Wins for B: 232 (46.4%) Python Programming, 2/e

556 Analysis and Specification
Notes: All inputs are assumed to be legal numeric values, no error or validity checking is required. In each simulated game, player A serves first. Python Programming, 2/e

557 PseudoRandom Numbers When we say that player A wins 50% of the time, that doesn’t mean they win every other game. Rather, it’s more like a coin toss. Overall, half the time the coin will come up heads, the other half the time it will come up tails, but one coin toss does not effect the next (it’s possible to get 5 heads in a row). Python Programming, 2/e

558 PseudoRandom Numbers Many simulations require events to occur with a certain likelihood. These sorts of simulations are called Monte Carlo simulations because the results depend on “chance” probabilities. Do you remember the chaos program from chapter 1? The apparent randomness of the result came from repeatedly applying a function to generate a sequence of numbers. Python Programming, 2/e

559 PseudoRandom Numbers A similar approach is used to generate random (technically pseudorandom) numbers. A pseudorandom number generator works by starting with a seed value. This value is given to a function to produce a “random” number. The next time a random number is required, the current value is fed back into the function to produce a new number. Python Programming, 2/e

560 PseudoRandom Numbers This sequence of numbers appears to be random, but if you start the process over again with the same seed number, you’ll get the same sequence of “random” numbers. Python provides a library module that contains a number of functions for working with pseudorandom numbers. Python Programming, 2/e

561 PseudoRandom Numbers These functions derive an initial seed value from the computer’s date and time when the module is loaded, so each time a program is run a different sequence of random numbers is produced. The two functions of greatest interest are randrange and random. Python Programming, 2/e

562 PseudoRandom Numbers The randrange function is used to select a pseudorandom int from a given range. The syntax is similar to that of the range command. randrange(1,6) returns some number from [1,2,3,4,5] and randrange(5,105,5) returns a multiple of 5 between 5 and 100, inclusive. Ranges go up to, but don’t include, the stopping value. Python Programming, 2/e

563 PseudoRandom Numbers Each call to randrange generates a new pseudorandom int. >>> from random import randrange >>> randrange(1,6) 5 3 2 4 Python Programming, 2/e

564 PseudoRandom Numbers The value 5 comes up over half the time, demonstrating the probabilistic nature of random numbers. Over time, this function will produce a uniform distribution, which means that all values will appear an approximately equal number of times. Python Programming, 2/e

565 PseudoRandom Numbers The random function is used to generate pseudorandom floating point values. It takes no parameters and returns values uniformly distributed between 0 and 1 (including 0 but excluding 1). Python Programming, 2/e

566 PseudoRandom Numbers >>> from random import random
Python Programming, 2/e

567 PseudoRandom Numbers The racquetball simulation makes use of the random function to determine if a player has won a serve. Suppose a player’s service probability is 70%, or 0.70. if <player wins serve>: score = score + 1 We need to insert a probabilistic function that will succeed 70% of the time. Python Programming, 2/e

568 PseudoRandom Numbers Suppose we generate a random number between 0 and 1. Exactly 70% of the interval 0..1 is to the left of 0.7. So 70% of the time the random number will be < 0.7, and it will be ≥ 0.7 the other 30% of the time. (The = goes on the upper end since the random number generator can produce a 0 but not a 1.) Python Programming, 2/e

569 PseudoRandom Numbers If prob represents the probability of winning the server, the condition random() < prob will succeed with the correct probability. if random() < prob: score = score + 1 Python Programming, 2/e

570 Top-Down Design In top-down design, a complex problem is expressed as a solution in terms of smaller, simpler problems. These smaller problems are then solved by expressing them in terms of smaller, simpler problems. This continues until the problems are trivial to solve. The little pieces are then put back together as a solution to the original problem! Python Programming, 2/e

571 Top-Level Design Typically a program uses the input, process, output pattern. The algorithm for the racquetball simulation: Print an introduction Get the inputs: probA, probB, n Simulate n games of racquetball using probA and probB Print a report on the wins for playerA and playerB Python Programming, 2/e

572 Top-Level Design Is this design too high level? Whatever we don’t know how to do, we’ll ignore for now. Assume that all the components needed to implement the algorithm have been written already, and that your task is to finish this top-level algorithm using those components. Python Programming, 2/e

573 Top-Level Design First we print an introduction.
This is easy, and we don’t want to bother with it. def main(): printIntro() We assume that there’s a printIntro function that prints the instructions! Python Programming, 2/e

574 Top-Level Design The next step is to get the inputs.
We know how to do that! Let’s assume there’s already a component that can do that called getInputs. getInputs gets the values for probA, probB, and n. def main(): printIntro() probA, probB, n = getInputs() Python Programming, 2/e

575 Top-Level Design Now we need to simulate n games of racquetball using the values of probA and probB. How would we do that? We can put off writing this code by putting it into a function, simNGames, and add a call to this function in main. Python Programming, 2/e

576 Top-Level Design If you were going to simulate the game by hand, what inputs would you need? probA probB n What values would you need to get back? The number of games won by player A The number of games won by player B These must be the outputs from the simNGames function. Python Programming, 2/e

577 Top-Level Design We now know that the main program must look like this: def main(): printIntro() probA, probB, n = getInputs() winsA, winsB = simNGames(n, probA, probB) What information would you need to be able to produce the output from the program? You’d need to know how many wins there were for each player – these will be the inputs to the next function. Python Programming, 2/e

578 Top-Level Design The complete main program: def main(): printIntro() probA, probB, n = getInputs() winsA, winsB = simNGames(n, probA, probB) printSummary(winsA, winsB) Python Programming, 2/e

579 Separation of Concerns
The original problem has now been decomposed into four independent tasks: printIntro getInputs simNGames printSummary The name, parameters, and expected return values of these functions have been specified. This information is known as the interface or signature of the function. Python Programming, 2/e

580 Separation of Concerns
Having this information (the signatures), allows us to work on each of these pieces indepently. For example, as far as main is concerned, how simNGames works is not a concern as long as passing the number of games and player probabilities to simNGames causes it to return the correct number of wins for each player. Python Programming, 2/e

581 Separation of Concerns
In a structure chart (or module hierarchy), each component in the design is a rectangle. A line connecting two rectangles indicates that the one above uses the one below. The arrows and annotations show the interfaces between the components. Python Programming, 2/e

582 Separation of Concerns
Python Programming, 2/e

583 Separation of Concerns
At each level of design, the interface tells us which details of the lower level are important. The general process of determining the important characteristics of something and ignoring other details is called abstraction. The top-down design process is a systematic method for discovering useful abstractions. Python Programming, 2/e

584 Second-Level Design The next step is to repeat the process for each of the modules defined in the previous step! The printIntro function should print an introduction to the program. The code for this is straightforward. Python Programming, 2/e

585 Second-Level Design def printIntro(): # Prints an introduction to the program print("This program simulates a game of racquetball between two") print('players called "A" and "B". The abilities of each player is') print("indicated by a probability (a number between 0 and 1) that") print("the player wins the point when serving. Player A always") print("has the first serve.\n“) In the second line, since we wanted double quotes around A and B, the string is enclosed in apostrophes. Since there are no new functions, there are no changes to the structure chart. Python Programming, 2/e

586 Second-Level Design In getInputs, we prompt for and get three values, which are returned to the main program. def getInputs(): # RETURNS probA, probB, number of games to simulate a = eval(input("What is the prob. player A wins a serve? ")) b = eval(input("What is the prob. player B wins a serve? ")) n = eval(input("How many games to simulate? ")) return a, b, n Python Programming, 2/e

587 Designing simNGames This function simulates n games and keeps track of how many wins there are for each player. “Simulate n games” sound like a counted loop, and tracking wins sounds like a good job for accumulator variables. Python Programming, 2/e

588 Designing simNGames Initialize winsA and winsB to 0 loop n times simulate a game if playerA wins Add one to winsA else Add one to winsB Python Programming, 2/e

589 Designing simNGames We already have the function signature: def simNGames(n, probA, probB): # Simulates n games of racquetball between players A and B # RETURNS number of wins for A, number of wins for B With this information, it’s easy to get started! def simNGames(n, probA, probB): # Simulates n games of racquetball between players A and B # RETURNS number of wins for A, number of wins for B winsA = winsB = for i in range(n): Python Programming, 2/e

590 Designing simNGames The next thing we need to do is simulate a game of racquetball. We’re not sure how to do that, so let’s put it off until later! Let’s assume there’s a function called simOneGame that can do it. The inputs to simOneGame are easy – the probabilities for each player. But what is the output? Python Programming, 2/e

591 Designing simNGames We need to know who won the game. How can we get this information? The easiest way is to pass back the final score. The player with the higher score wins and gets their accumulator incremented by one. Python Programming, 2/e

592 Designing simNGames def simNGames(n, probA, probB):
# Simulates n games of racquetball between players A and B # RETURNS number of wins for A, number of wins for B winsA = winsB = 0 for i in range(n): scoreA, scoreB = simOneGame(probA, probB) if scoreA > scoreB: winsA = winsA + 1 else: winsB = winsB + 1 return winsA, winsB Python Programming, 2/e

593 Designing simNGames Python Programming, 2/e

594 Third-Level Design The next function we need to write is simOneGame, where the logic of the racquetball rules lies. Players keep doing rallies until the game is over, which implies the use of an indefinite loop, since we don’t know ahead of time how many rallies there will be before the game is over. Python Programming, 2/e

595 Third-Level Design We also need to keep track of the score and who’s serving. The score will be two accumulators, so how do we keep track of who’s serving? One approach is to use a string value that alternates between “A” or “B”. Python Programming, 2/e

596 Third-Level Design Initialize scores to 0 Set serving to “A” Loop while game is not over: Simulate one serve of whichever player is serving update the status of the game Return scores Def simOneGame(probA, probB): scoreA = 0 scoreB = 0 serving = “A” while <condition>: What will the condition be?? Let’s take the two scores and pass them to another function that returns True if the game is over, False if not. Python Programming, 2/e

597 Third-Level Design Python Programming, 2/e

598 Third-Level Design At this point, simOneGame looks like this:
def simOneGame(probA, probB): # Simulates a single game or racquetball between players A and B # RETURNS A's final score, B's final score serving = "A“ scoreA = scoreB = while not gameOver(scoreA, scoreB): Python Programming, 2/e

599 Third-Level Design Inside the loop, we need to do a single serve. We’ll compare a random number to the provided probability to determine if the server wins the point (random() < prob). The probability we use is determined by whom is serving, contained in the variable serving. Python Programming, 2/e

600 Third-Level Design If A is serving, then we use A’s probability, and based on the result of the serve, either update A’s score or change the service to B. if serving == "A": if random() < probA: scoreA = scoreA else: serving = "B" Python Programming, 2/e

601 Third-Level Design Likewise, if it’s B’s serve, we’ll do the same thing with a mirror image of the code. if serving == "A": if random() < probA: scoreA = scoreA else: serving = "B“ else: if random() < probB: scoreB = scoreB else: serving = "A" Python Programming, 2/e

602 Third-Level Design Putting the function together: def simOneGame(probA, probB): # Simulates a single game or racquetball between players A and B # RETURNS A's final score, B's final score serving = "A" scoreA = 0 scoreB = 0 while not gameOver(scoreA, scoreB): if serving == "A": if random() < probA: scoreA = scoreA + 1 else: serving = "B" if random() < probB: scoreB = scoreB + 1 return scoreA, scoreB Python Programming, 2/e

603 Finishing Up There’s just one tricky function left, gameOver. Here’s what we know: def gameOver(a,b): # a and b are scores for players in a racquetball game # RETURNS true if game is over, false otherwise According to the rules, the game is over when either player reaches 15 points. We can check for this with the boolean: a==15 or b==15 Python Programming, 2/e

604 Finishing Up So, the complete code for gameOver looks like this: def gameOver(a,b): # a and b are scores for players in a racquetball game # RETURNS true if game is over, false otherwise return a == 15 or b == 15 printSummary is equally simple! def printSummary(winsA, winsB): # Prints a summary of wins for each player. n = winsA + winsB print "\nGames simulated:", n print "Wins for A: {0} ({1:0.1%})".format(winsA, winsA)/n) print "Wins for B: {0} ({1:0.1%})".format(winsB, winsB/n) Notice % formatting on the output Python Programming, 2/e

605 Summary of the Design Process
We started at the highest level of our structure chart and worked our way down. At each level, we began with a general algorithm and refined it into precise code. This process is sometimes referred to as step-wise refinement. Python Programming, 2/e

606 Summary of the Design Process
Express the algorithm as a series of smaller problems. Develop an interface for each of the small problems. Detail the algorithm by expressing it in terms of its interfaces with the smaller problems. Repeat the process for each smaller problem. Python Programming, 2/e

607 Bottom-Up Implementation
Even though we’ve been careful with the design, there’s no guarantee we haven’t introduced some silly errors. Implementation is best done in small pieces. Python Programming, 2/e

608 Unit Testing A good way to systematically test the implementation of a modestly sized program is to start at the lowest levels of the structure, testing each component as it’s completed. For example, we can import our program and execute various routines/functions to ensure they work properly. Python Programming, 2/e

609 Unit Testing We could start with the gameOver function.
>>> import rball >>> rball.gameOver(0,0) False >>> rball.gameOver(5,10) False >>> rball.gameOver(15,3) True >>> rball.gameOver(3,15) True Python Programming, 2/e

610 Unit Testing Notice that we’ve tested gameOver for all the important cases. We gave it 0, 0 as inputs to simulate the first time the function will be called. The second test is in the middle of the game, and the function correctly reports that the game is not yet over. The last two cases test to see what is reported when either player has won. Python Programming, 2/e

611 Unit Testing Now that we see that gameOver is working, we can go on to simOneGame. >>> simOneGame(.5, .5) (11, 15) (13, 15) >>> simOneGame(.3, .3) (15, 4) >>> simOneGame(.4, .9) (2, 15) (1, 15) >>> simOneGame(.9, .4) (15, 0) >>> simOneGame(.4, .6) (10, 15) (9, 15) Python Programming, 2/e

612 Unit Testing When the probabilities are equal, the scores aren’t that far apart. When the probabilities are farther apart, the game is a rout. Testing each component in this manner is called unit testing. Testing each function independently makes it easier to spot errors, and should make testing the entire program go more smoothly. Python Programming, 2/e

613 Simulation Results Is it the nature of racquetball that small differences in ability lead to large differences in final score? Suppose Denny wins about 60% of his serves and his opponent is 5% better. How often should Denny win? Let’s do a sample run where Denny’s opponent serves first. Python Programming, 2/e

614 Simulation Results This program simulates a game of racquetball between two players called "A" and "B". The abilities of each player is indicated by a probability (a number between 0 and 1) that the player wins the point when serving. Player A always has the first serve. What is the prob. player A wins a serve? .65 What is the prob. player B wins a serve? .6 How many games to simulate? 5000 Games simulated: 5000 Wins for A: 3329 (66.6%) Wins for B: 1671 (33.4%) With this small difference in ability , Denny will win only 1 in 3 games! Python Programming, 2/e

615 Other Design Techniques
Top-down design is not the only way to create a program! Python Programming, 2/e

616 Prototyping and Spiral Development
Another approach to program development is to start with a simple version of a program, and then gradually add features until it meets the full specification. This initial stripped-down version is called a prototype. Python Programming, 2/e

617 Prototyping and Spiral Development
Prototyping often leads to a spiral development process. Rather than taking the entire problem and proceeding through specification, design, implementation, and testing, we first design, implement, and test a prototype. We take many mini-cycles through the development process as the prototype is incrementally expanded into the final program. Python Programming, 2/e

618 Prototyping and Spiral Development
How could the racquetball simulation been done using spiral development? Write a prototype where you assume there’s a chance of winning any given point, playing 30 rallies. Add on to the prototype in stages, including awarding of points, change of service, differing probabilities, etc. Python Programming, 2/e

619 Prototyping and Spiral Development
from random import random def simOneGame(): scoreA = 0 scoreB = 0 serving = "A" for i in range(30): if serving == "A": if random() < .5: scoreA = scoreA + 1 else: serving = "B" scoreB = scoreB + 1 print(scoreA, scoreB) >>> simOneGame() 0 0 0 1 2 7 2 8 3 8 3 9 4 9 5 9 Python Programming, 2/e

620 Prototyping and Spiral Development
The program could be enhanced in phases: Phase 1: Initial prototype. Play 30 rallies where the server always has a 50% chance of winning. Print out the scores after each server. Phase 2: Add two parameters to represent different probabilities for the two players. Python Programming, 2/e

621 Prototyping and Spiral Development
Phase 3: Play the game until one of the players reaches 15 points. At this point, we have a working simulation of a single game. Phase 4: Expand to play multiple games. The output is the count of games won by each player. Phase 5: Build the complete program. Add interactive inputs and a nicely formatted report of the results. Python Programming, 2/e

622 Prototyping and Spiral Development
Spiral development is useful when dealing with new or unfamiliar features or technology. If top-down design isn’t working for you, try some spiral development! Python Programming, 2/e

623 The Art of Design Spiral development is not an alternative to top-down design as much as a complement to it – when designing the prototype you’ll still be using top-down techniques. Good design is as much creative process as science, and as such, there are no hard and fast rules. Python Programming, 2/e

624 The Art of Design The best advice? Practice, practice, practice
Python Programming, 2/e

625 Python Programming: An Introduction To Computer Science
Chapter 10 Defining Classes Python Programming, 2/e

626 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, 2/e Python Programming, 1/e

627 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, 2/e

628 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, 2/e

629 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: A collection of related information. A set of operations to manipulate that information. Python Programming, 2/e

630 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, 2/e

631 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, 2/e

632 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, 2/e

633 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, 2/e

634 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, 2/e

635 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: myCircle.draw(win) myCircle.move(dx,dy) Python Programming, 2/e

636 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, 2/e

637 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, 2/e

638 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, 2/e

639 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, 2/e

640 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, 2/e

641 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, 2/e

642 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, 2/e

643 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, 2/e

644 Designing the Program Using step-wise refinement: def main(): angle = eval(input("Enter the launch angle (in degrees): ")) vel = eval(input("Enter the initial velocity (in meters/sec): ")) h0 = eval(input("Enter the initial height (in meters): ")) time = eval(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 = ypos = h0 Python Programming, 2/e

645 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, 2/e

646 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, 2/e

647 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 meters away. If the time increment is .1 second it will be *.1 = 53 meters. xpos = xpos + time * xvel Python Programming, 2/e

648 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 * time Python Programming, 2/e

649 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, 2/e

650 Designing Programs Python Programming, 2/e # cball1.py
# 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 = eval(input("Enter the launch angle (in degrees): ")) vel = eval(input("Enter the initial velocity (in meters/sec): ")) h0 = eval(input("Enter the initial height (in meters): ")) time = eval(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 * time ypos = ypos + time * (yvel + yvel1)/2.0 yvel = yvel1 print("\nDistance traveled: {0:0.1f} meters." .format(xpos) main() Python Programming, 2/e

651 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, 2/e

652 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:0.1f} meters.".format(xpos) It should be obvious what each of these helper functions does based on their name and the original program code. Python Programming, 2/e

653 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, 2/e

654 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, 2/e

655 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, 2/e

656 Modularizing the Program
Using our object-based approach: def main(): angle, vel, h0, time = getInputs() cball = Projectile(angle, vel, h0) while cball.getY() >= 0: cball.update(time) print("\nDistance traveled: {0:0.1f} meters.".format(cball.getX())) main() To make this work we need a Projectile class that implements the methods update, getX, and getY. Python Programming, 2/e

657 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, 2/e

658 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, 2/e

659 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, 2/e

660 Example: Multi-Sided Dice
>>> die1 = MSDie(6) >>> die1.getValue() 1 >>> die1.roll() 5 >>> die2 = MSDie(13) >>> die2.getValue() >>> die2.roll() 9 >>> die2.setValue(8) 8 Python Programming, 2/e

661 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, 2/e

662 Example: Multi-Sided Dice
# msdie.py # Class definition for an n-sided die. from random import randrange class MSDie: def __init__(self, sides): self.sides = sides self.value = 1 def roll(self): self.value = randrange(1, self.sides+1) def getValue(self): return self.value def setValue(self, value): self.value = value Python Programming, 2/e

663 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, 2/e

664 Example: Multi-Sided Dice
Suppose we have a main function that executes die1.setValue(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, 2/e

665 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, 2/e

666 Example: Multi-Sided Dice
Control returns to the point just after where the method was called. In this case, it is immediately following die1.setValue(8). Methods are called with one parameter, but the method definition itself includes the self parameter as well as the actual parameter. Python Programming, 2/e

667 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, 2/e

668 Example: Multi-Sided Dice
Python Programming, 2/e

669 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 self.value refers to the instance variable value inside the object. Each MSDie object has its own value. Python Programming, 2/e

670 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, 2/e

671 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 die1.sides is set to 6 and die1.value is set to 1. Python Programming, 2/e

672 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, 2/e

673 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, 2/e

674 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, 2/e

675 Example: The Projectile Class
class Projectile: def __init__(self, angle, velocity, height): self.xpos = 0.0 self.ypos = height theta = pi * angle / 180.0 self.xvel = velocity * cos(theta) self.yvel = velocity * sin(theta) We’ve created four instance variables (self.???). Since the value of theta is not needed later, it is a normal function variable. Python Programming, 2/e

676 Example: The Projectile Class
The methods to access the X and Y position are straightforward. def getY(self): return self.ypos def getX(self): return self.xpos Python Programming, 2/e

677 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): self.xpos = self.xpos + time * self.xvel yvel1 = self.yvel * time self.ypos = self.ypos + time * (self.yvel + yvel1) / 2.0 self.yvel = yvel1 yvel1 is a temporary variable. Python Programming, 2/e

678 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, 2/e

679 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, 2/e

680 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, 2/e

681 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 Comptewell, Susan DibbleBit, Denny Jones, Jim Smith, Frank Python Programming, 2/e

682 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, 2/e

683 Data Processing with Class
class Student: def __init__(self, name, hours, qpoints): self.name = name self.hours = float(hours) self.qpoints = 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, 2/e

684 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 self.name def getHours(self): return self.hours def getQPoints(self): return self.qpoints def gpa(self): return self.qpoints/self.hours For example, to print a student’s name you could write: print aStudent.getName() Python Programming, 2/e

685 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, 2/e

686 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 s.gpa() > best.gpa set best to s Print out information about best Python Programming, 2/e

687 Data Processing with Class
# gpa.py # Program to find student with highest GPA class Student: def __init__(self, name, hours, qpoints): self.name = name self.hours = float(hours) self.qpoints = float(qpoints) def getName(self): return self.name def getHours(self): return self.hours def getQPoints(self): return self.qpoints def gpa(self): return self.qpoints/self.hours def makeStudent(infoStr): name, hours, qpoints = infoStr.split("\t") return Student(name, hours, qpoints) def main(): filename = input("Enter name the grade file: ") infile = open(filename, 'r') best = makeStudent(infile.readline()) for line in infile: s = makeStudent(line) if s.gpa() > best.gpa(): best = s infile.close() print("The best student is:", best.getName()) print ("hours:", best.getHours()) print("GPA:", best.gpa()) if __name__ == '__main__': main() Python Programming, 2/e

688 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, 2/e

689 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, 2/e

690 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, 2/e

691 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, 2/e

692 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, 2/e

693 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, 2/e

694 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 random.random.__doc__ random() -> x in the interval [0, 1). Python Programming, 2/e

695 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(random.random) Help on built-in function random: random(...) random() -> x in the interval [0, 1). Python Programming, 2/e

696 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, 2/e

697 Module Documentation Python Programming, 2/e # projectile.py
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.""" self.xpos = 0.0 self.ypos = height theta = pi * angle / 180.0 self.xvel = velocity * cos(theta) self.yvel = velocity * sin(theta) Python Programming, 2/e

698 Module Documentation def update(self, time):
"""Update the state of this projectile to move it time seconds farther into its flight""" self.xpos = self.xpos + time * self.xvel yvel1 = self.yvel * time self.ypos = self.ypos + time * (self.yvel + yvel1) / 2.0 self.yvel = yvel1 def getY(self): "Returns the y position (height) of this projectile." return self.ypos def getX(self): "Returns the x position (distance) of this projectile." return self.xpos Python Programming, 2/e

699 Working with Multiple Modules
Our main program can import from the projectile module in order to solve the original problem! # cball4.py # 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 = eval(input("Enter the launch angle (in degrees): ")) v = eval(input("Enter the initial velocity (in meters/sec): ")) h = eval(input("Enter the initial height (in meters): ")) t = eval(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 cball.getY() >= 0: cball.update(time) print("\nDistance traveled: {0:0.1f} meters.".format(cball.getX()) Python Programming, 2/e

700 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, 2/e

701 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, 2/e

702 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, 2/e

703 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, 2/e

704 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, 2/e

705 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, 2/e

706 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, 2/e

707 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, 2/e

708 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, 2/e

709 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, 2/e

710 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, 2/e

711 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'. " self.label.setFill('black') self.rect.setWidth(2) self.active = True Remember, self refers to the button object. Our constructor will have to initialize self.label as an appropriate Text object and self.rect as a rectangle object. Self.active also has a Boolean instance variable to remember whether or not the button is currently inactive. Python Programming, 2/e

712 Building Buttons The code for deactivate is very similar: def deactivate(self): "Sets this button to 'inactive'." self.label.setFill('darkgrey') self.rect.setWidth(1) self.active = 0 Python Programming, 2/e

713 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, 2/e

714 Building Buttons pt = win.getMouse() if button1.clicked(pt): # Do button1 stuff elif button2.clicked(pt): # Do button2 stuff elif button3.clicked(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, 2/e

715 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, 2/e

716 Building Buttons def clicked(self, p): "RETURNS true if button active and p is inside“ return self.active and \ self.xmin <= p.getX() <= self.xmax and \ self.ymin <= p.getY() <= self.ymax 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, 2/e

717 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 = center.getX(), center.getY() self.xmax, self.xmin = x+w, x-w self.ymax, self.ymin = y+h, y-h p1 = Point(self.xmin, self.ymin) p2 = Point(self.xmax, self.ymax) self.rect = Rectangle(p1,p2) self.rect.setFill('lightgray') self.rect.draw(win) self.label = Text(center, label) self.label.draw(win) self.deactivate() Buttons are positioned by providing a center point, width, and height. Python Programming, 2/e

718 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, 2/e

719 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, 2/e

720 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, 2/e

721 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, 2/e

722 Building Dice Python Programming, 2/e # dieview.py
# 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 self.win = win self.background = "white" # color of die face self.foreground = "black" # color of the pips self.psize = 0.1 * size # radius of each pip hsize = size / # half of size offset = 0.6 * hsize # distance from center to outer pip Python Programming, 2/e

723 Building Dice # create a square for the face
cx, cy = center.getX(), center.getY() p1 = Point(cx-hsize, cy-hsize) p2 = Point(cx+hsize, cy+hsize) rect = Rectangle(p1,p2) rect.draw(win) rect.setFill(self.background) # 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) self.setValue(1) Python Programming, 2/e

724 Building Dice def __makePip(self, x, y):
"""Internal helper method to draw a pip at (x,y)""" pip = Circle(Point(x,y), self.psize) pip.setFill(self.background) pip.setOutline(self.background) pip.draw(self.win) return pip def setValue(self, value): """ Set this die to display value.""" # turn all pips off self.pip1.setFill(self.background) self.pip2.setFill(self.background) self.pip3.setFill(self.background) self.pip4.setFill(self.background) self.pip5.setFill(self.background) self.pip6.setFill(self.background) self.pip7.setFill(self.background) Python Programming, 2/e

725 Building Dice Python Programming, 2/e # turn correct pips on
if value == 1: self.pip4.setFill(self.foreground) elif value == 2: self.pip1.setFill(self.foreground) self.pip7.setFill(self.foreground) elif value == 3: elif value == 4: self.pip3.setFill(self.foreground) self.pip5.setFill(self.foreground) elif value == 5: else: self.pip2.setFill(self.foreground) self.pip6.setFill(self.foreground) Python Programming, 2/e

726 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, 2/e

727 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, 2/e

728 The Main Program Python Programming, 2/e # roller.py
# 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") win.setCoords(0, 0, 10, 10) win.setBackground("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") rollButton.activate() quitButton = Button(win, Point(5,1), 2, 1, "Quit") Python Programming, 2/e

729 The Main Program Python Programming, 2/e # Event loop
pt = win.getMouse() while not quitButton.clicked(pt): if rollButton.clicked(pt): value1 = randrange(1,7) die1.setValue(value1) value2 = randrange(1,7) die2.setValue(value2) quitButton.activate() # close up shop win.close() main() Python Programming, 2/e

730 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, 2/e

731 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, 2/e

732 Python Programing: An Introduction to Computer Science
Chapter 11 Data Collections Python Programming, 2/e

733 Objectives To understand the use of lists (arrays) to represent a collection of related data. To be familiar with the functions and methods available for manipulating Python lists. To be able to write programs that use lists to manage a collection of information. Python Programming, 2/e

734 Objectives To be able to write programs that use lists and classes to structure complex data. To understand the use of Python dictionaries for storing nonsequential collections. Python Programming, 2/e

735 Example Problem: Simple Statistics
Many programs deal with large collections of similar information. Words in a document Students in a course Data from an experiment Customers of a business Graphics objects drawn on the screen Cards in a deck Python Programming, 2/e

736 Sample Problem: Simple Statistics
Let’s review some code we wrote in chapter 8: # average4.py # A program to average a set of numbers # Illustrates sentinel loop using empty string as sentinel def main(): sum = 0.0 count = 0 xStr = input("Enter a number (<Enter> to quit) >> ") while xStr != "": x = eval(xStr) sum = sum + x count = count + 1 print("\nThe average of the numbers is", sum / count) main() Python Programming, 2/e Python Programming, 1/e

737 Sample Problem: Simple Statistics
This program allows the user to enter a sequence of numbers, but the program itself doesn’t keep track of the numbers that were entered – it only keeps a running total. Suppose we want to extend the program to compute not only the mean, but also the median and standard deviation. Python Programming, 2/e

738 Sample Problem: Simple Statistics
The median is the data value that splits the data into equal-sized parts. For the data 2, 4, 6, 9, 13, the median is 6, since there are two values greater than 6 and two values that are smaller. One way to determine the median is to store all the numbers, sort them, and identify the middle value. Python Programming, 2/e

739 Sample Problem: Simple Statistics
The standard deviation is a measure of how spread out the data is relative to the mean. If the data is tightly clustered around the mean, then the standard deviation is small. If the data is more spread out, the standard deviation is larger. The standard deviation is a yardstick to measure/express how exceptional the data is. Python Programming, 2/e

740 Sample Problem: Simple Statistics
The standard deviation is Here is the mean, represents the ith data value and n is the number of data values. The expression is the square of the “deviation” of an individual item from the mean. Python Programming, 2/e

741 Sample Problem: Simple Statistics
The numerator is the sum of these squared “deviations” across all the data. Suppose our data was 2, 4, 6, 9, and 13. The mean is 6.8 The numerator of the standard deviation is Python Programming, 2/e

742 Sample Problem: Simple Statistics
As you can see, calculating the standard deviation not only requires the mean (which can’t be calculated until all the data is entered), but also each individual data element! We need some way to remember these values as they are entered. Python Programming, 2/e

743 Applying Lists We need a way to store and manipulate an entire collection of numbers. We can’t just use a bunch of variables, because we don’t know many numbers there will be. What do we need? Some way of combining an entire collection of values into one object. Python Programming, 2/e

744 Lists and Arrays Python lists are ordered sequences of items. For instance, a sequence of n numbers might be called S: S = s0, s1, s2, s3, …, sn-1 Specific values in the sequence can be referenced using subscripts. By using numbers as subscripts, mathematicians can succinctly summarize computations over items in a sequence using subscript variables. Python Programming, 2/e

745 Lists and Arrays Suppose the sequence is stored in a variable s. We could write a loop to calculate the sum of the items in the sequence like this: sum = 0 for i in range(n): sum = sum + s[i] Almost all computer languages have a sequence structure like this, sometimes called an array. Python Programming, 2/e

746 Lists and Arrays A list or array is a sequence of items where the entire sequence is referred to by a single name (i.e. s) and individual items can be selected by indexing (i.e. s[i]). In other programming languages, arrays are generally a fixed size, meaning that when you create the array, you have to specify how many items it can hold. Arrays are generally also homogeneous, meaning they can hold only one data type. Python Programming, 2/e

747 Lists and Arrays Python lists are dynamic. They can grow and shrink on demand. Python lists are also heterogeneous, a single list can hold arbitrary data types. Python lists are mutable sequences of arbitrary objects. Python Programming, 2/e

748 List Operations Operator Meaning <seq> + <seq>
Concatenation <seq> * <int-expr> Repetition <seq>[] Indexing len(<seq>) Length <seq>[:] Slicing for <var> in <seq>: Iteration <expr> in <seq> Membership (Boolean) Python Programming, 2/e

749 List Operations Except for the membership check, we’ve used these operations before on strings. The membership operation can be used to see if a certain value appears anywhere in a sequence. >>> lst = [1,2,3,4] >>> 3 in lst True Python Programming, 2/e

750 List Operations The summing example from earlier can be written like this: sum = 0 for x in s: sum = sum + x Unlike strings, lists are mutable: >>> lst = [1,2,3,4] >>> lst[3] 4 >>> lst[3] = "Hello“ >>> lst [1, 2, 3, 'Hello'] >>> lst[2] = 7 >>> lst [1, 2, 7, 'Hello'] Python Programming, 2/e

751 List Operations A list of identical items can be created using the repetition operator. This command produces a list containing 50 zeroes: zeroes = [0] * 50 Python Programming, 2/e

752 List Operations Lists are often built up one piece at a time using append. nums = [] x = eval(input('Enter a number: ')) while x >= 0: nums.append(x) x = eval(input('Enter a number: ')) Here, nums is being used as an accumulator, starting out empty, and each time through the loop a new value is tacked on. Python Programming, 2/e

753 List Operations Method Meaning <list>.append(x)
Add element x to end of list. <list>.sort() Sort (order) the list. A comparison function may be passed as a parameter. <list>.reverse() Reverse the list. <list>.index(x) Returns index of first occurrence of x. <list>.insert(i, x) Insert x into list at index i. <list>.count(x) Returns the number of occurrences of x in list. <list>.remove(x) Deletes the first occurrence of x in list. <list>.pop(i) Deletes the ith element of the list and returns its value. Python Programming, 2/e

754 List Operations Python Programming, 2/e
>>> lst = [3, 1, 4, 1, 5, 9] >>> lst.append(2) >>> lst [3, 1, 4, 1, 5, 9, 2] >>> lst.sort() [1, 1, 2, 3, 4, 5, 9] >>> lst.reverse() [9, 5, 4, 3, 2, 1, 1] >>> lst.index(4) 2 >>> lst.insert(4, "Hello") [9, 5, 4, 3, 'Hello', 2, 1, 1] >>> lst.count(1)s >>> lst.remove(1) [9, 5, 4, 3, 'Hello', 2, 1] >>> lst.pop(3) 3 [9, 5, 4, 'Hello', 2, 1] Python Programming, 2/e

755 List Operations Most of these methods don’t return a value – they change the contents of the list in some way. Lists can grow by appending new items, and shrink when items are deleted. Individual items or entire slices can be removed from a list using the del operator. Python Programming, 2/e

756 List Operations >>> myList=[34, 26, 0, 10] >>> del myList[1] >>> myList [34, 0, 10] >>> del myList[1:3] >>> myList [34] del isn’t a list method, but a built-in operation that can be used on list items. Python Programming, 2/e

757 List Operations Basic list principles
A list is a sequence of items stored as a single object. Items in a list can be accessed by indexing, and sublists can be accessed by slicing. Lists are mutable; individual items or entire slices can be replaced through assignment statements. Python Programming, 2/e

758 List Operations Lists support a number of convenient and frequently used methods. Lists will grow and shrink as needed. Python Programming, 2/e

759 Statistics with Lists One way we can solve our statistics problem is to store the data in lists. We could then write a series of functions that take a list of numbers and calculates the mean, standard deviation, and median. Let’s rewrite our earlier program to use lists to find the mean. Python Programming, 2/e

760 Statistics with Lists Let’s write a function called getNumbers that gets numbers from the user. We’ll implement the sentinel loop to get the numbers. An initially empty list is used as an accumulator to collect the numbers. The list is returned once all values have been entered. Python Programming, 2/e

761 Statistics with Lists def getNumbers(): nums = [] # start with an empty list # sentinel loop to get numbers xStr = input("Enter a number (<Enter> to quit) >> ") while xStr != "": x = eval(xStr) nums.append(x) # add this value to the list return nums Using this code, we can get a list of numbers from the user with a single line of code: data = getNumbers() Python Programming, 2/e

762 Statistics with Lists Now we need a function that will calculate the mean of the numbers in a list. Input: a list of numbers Output: the mean of the input list def mean(nums): sum = for num in nums: sum = sum + num return sum / len(nums) Python Programming, 2/e

763 Statistics with Lists The next function to tackle is the standard deviation. In order to determine the standard deviation, we need to know the mean. Should we recalculate the mean inside of stdDev? Should the mean be passed as a parameter to stdDev? Python Programming, 2/e

764 Statistics with Lists Recalculating the mean inside of stdDev is inefficient if the data set is large. Since our program is outputting both the mean and the standard deviation, let’s compute the mean and pass it to stdDev as a parameter. Python Programming, 2/e

765 Statistics with Lists def stdDev(nums, xbar): sumDevSq = for num in nums: dev = xbar - num sumDevSq = sumDevSq + dev * dev return sqrt(sumDevSq/(len(nums)-1)) The summation from the formula is accomplished with a loop and accumulator. sumDevSq stores the running sum of the squares of the deviations. Python Programming, 2/e

766 Statistics with Lists We don’t have a formula to calculate the median. We’ll need to come up with an algorithm to pick out the middle value. First, we need to arrange the numbers in ascending order. Second, the middle value in the list is the median. If the list has an even length, the median is the average of the middle two values. Python Programming, 2/e

767 Statistics with Lists Pseudocode -
sort the numbers into ascending order if the size of the data is odd: median = the middle value else: median = the average of the two middle values return median Python Programming, 2/e

768 Statistics with Lists def median(nums): nums.sort() size = len(nums)
midPos = size // 2 if size % 2 == 0: median = (nums[midPos] + nums[midPos-1]) / 2 else: median = nums[midPos] return median Python Programming, 2/e

769 Statistics with Lists With these functions, the main program is pretty simple! def main(): print("This program computes mean, median and standard deviation.") data = getNumbers() xbar = mean(data) std = stdDev(data, xbar) med = median(data) print("\nThe mean is", xbar) print("The standard deviation is", std) print("The median is", med) Python Programming, 2/e

770 Statistics with Lists Statistical analysis routines might come in handy some time, so let’s add the capability to use this code as a module by adding: if __name__ == '__main__': main() Python Programming, 2/e

771 Lists of Objects All of the list examples we’ve looked at so far have involved simple data types like numbers and strings. We can also use lists to store more complex data types, like our student information from chapter ten. Python Programming, 2/e

772 Lists of Objects Our grade processing program read through a file of student grade information and then printed out information about the student with the highest GPA. A common operation on data like this is to sort it, perhaps alphabetically, perhaps by credit-hours, or even by GPA. Python Programming, 2/e

773 Lists of Objects Let’s write a program that sorts students according to GPA using our Sutdent class from the last chapter. Get the name of the input file from the user Read student information into a list Sort the list by GPA Get the name of the output file from the user Write the student information from the list into a file Python Programming, 2/e

774 Lists of Objects Let’s begin with the file processing. The following code reads through the data file and creates a list of students. def readStudents(filename): infile = open(filename, 'r') students = [] for line in infile: students.append(makeStudent(line)) infile.close() return students We’re using the makeStudent from the gpa program, so we’ll need to remember to import it. Python Programming, 2/e

775 Lists of Objects Let’s also write a function to write the list of students back to a file. Each line should contain three pieces of information, separated by tabs: name, credit hours, and quality points. def writeStudents(students, filename): # students is a list of Student objects outfile = open(filename, 'w') for s in students: print((s.getName(),s.getHours(),s.getQPoints(), sep="\t", file=outfile) outfile.close() Python Programming, 2/e

776 Lists of Objects Using the functions readStudents and writeStudents, we can convert our data file into a list of students and then write them back to a file. All we need to do now is sort the records by GPA. In the statistics program, we used the sort method to sort a list of numbers. How does Python sort lists of objects? Python Programming, 2/e

777 Lists of Objects To make sorting work with our objects, we need to tell sort how the objects should be compared. Can supply a function to produce the key for an object using <list>.sort(key=<somefunc>) To sort by GPA, we need a function that takes a Student as parameter and returns the student's GPA. Python Programming, 2/e

778 Lists of Objects def use_gpa(aStudent): return aStudent.gpa() We can now sort the data by calling sort with the key function as a keyword parameter. data.sort(key=use_gpa) Python Programming, 2/e

779 Lists of Objects data.sort(key=use_gpa)
Notice that we didn’t put ()’s after the function name. This is because we don’t want to call use_gpa, but rather, we want to send use_gpa to the sort method. Python Programming, 2/e

780 Lists of Objects Actually, defining use_gpa was unnecessary.
The gpa method in the Student class is a function that takes a student as a parameter (formally, self) and returns GPA. Can use it: data.sort(key=Student.gpa) Python Programming, 2/e

781 Lists of Objects Python Programming, 2/e def main(): # gpasort.py
print ("This program sorts student grade information by GPA") filename = input("Enter the name of the data file: ") data = readStudents(filename) data.sort(Student.gpa) filename = input("Enter a name for the output file: ") writeStudents(data, filename) print("The data has been written to", filename) if __name__ == '__main__': main() # gpasort.py # A program to sort student information into GPA order. from gpa import Student, makeStudent def readStudents(filename): infile = open(filename, 'r') students = [] for line in infile: students.append(makeStudent(line)) infile.close() return students def writeStudents(students, filename): outfile = open(filename, 'w') for s in students: print(s.getName(), s.getHours(), s.getQPoints(), sep="\t", file=outfile) outfile.close() Python Programming, 2/e

782 Designing with Lists and Classes
In the dieView class from chapter ten, each object keeps track of seven circles representing the position of pips on the face of the die. Previously, we used specific instance variables to keep track of each, pip1, pip2, pip3, … Python Programming, 2/e

783 Designing with Lists and Classes
What happens if we try to store the circle objects using a list? In the previous program, the pips were created like this: self.pip1 = self.__makePip(cx, cy) __makePip is a local method of the DieView class that creates a circle centered at the position given by its parameters. Python Programming, 2/e

784 Designing with Lists and Classes
One approach is to start with an empty list of pips and build up the list one pip at a time. pips = [] pips.append(self.__makePip(cx-offset,cy-offset) pips.append(self.__makePip(cx-offset,cy) … self.pips = pips Python Programming, 2/e

785 Designing with Lists and Classes
An even more straightforward approach is to create the list directly. self.pips = [self.__makePip(cx-offset,cy-offset), self.__makePip(cx-offset,cy), … self.__makePip(cx+offset,cy+offset) ] Python is smart enough to know that this object is continued over a number of lines, and waits for the ‘]’. Listing objects like this, one per line, makes it much easier to read. Python Programming, 2/e

786 Designing with Lists and Classes
Putting our pips into a list makes many actions simpler to perform. To blank out the die by setting all the pips to the background color: for pip in self.pips: pip.setFill(self.background) This cut our previous code from seven lines to two! Python Programming, 2/e

787 Designing with Lists and Classes
We can turn the pips back on using the pips list. Our original code looked like this: self.pip1.setFill(self.foreground) self.pip4.setFill(self.foreground) self.pip7.setFill(self.foreground) Into this: self.pips[0].setFill(self.foreground) self.pips[3].setFill(self.foreground) self.pips[6].setFill(self.foreground) Python Programming, 2/e

788 Designing with Lists and Classes
Here’s an even easier way to access the same methods: for i in [0,3,6]: self.pips[i].setFill(self.foreground) We can take advantage of this approach by keeping a list of which pips to activate! Loop through pips and turn them all off Determine the list of pip indexes to turn on Loop through the list of indexes - turn on those pips Python Programming, 2/e

789 Designing with Lists and Classes
for pip in self.pips: self.pip.setFill(self.background) if value == 1: on = [3] elif value == 2: on = [0,6] elif value == 3: on = [0,3,6] elif value == 4: on = [0,2,4,6] elif value == 5: on = [0,2,3,4,6] else: on = [0,1,2,3,4,5,6] for i in on: self.pips[i].setFill(self.foreground) Python Programming, 2/e

790 Designing with Lists and Classes
We can do even better! The correct set of pips is determined by value. We can make this process table-driven instead. We can use a list where each item on the list is itself a list of pip indexes. For example, the item in position 3 should be the list [0,3,6] since these are the pips that must be turned on to show a value of 3. Python Programming, 2/e

791 Designing with Lists and Classes
Here’s the table-driven code: onTable = [ [], [3], [2,4], [2,3,4], [0,2,4,6], [0,2,3,4,6], [0,1,2,4,5,6] ] for pip in self.pips: self.pip.setFill(self.background) on = onTable[value] for i in on: self.pips[i].setFill(self.foreground) Python Programming, 2/e

792 Designing with Lists and Classes
onTable = [ [], [3], [2,4], [2,3,4], [0,2,4,6], [0,2,3,4,6], [0,1,2,4,5,6] ] for pip in self.pips: self.pip.setFill(self.background) on = onTable[value] for i in on: self.pips[i].setFill(self.foreground) The table is padded with ‘[]’ in the 0 position, since it shouldn’t ever be used. The onTable will remain unchanged through the life of a dieView, so it would make sense to store this table in the constructor and save it in an instance variable. Python Programming, 2/e

793 Designing with Lists and Classes
# dieview2.py # A widget for displaying the value of a die. # This version uses lists to simplify keeping track of pips. 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 define some standard values self.win = win self.background = "white" # color of die face self.foreground = "black" # color of the pips self.psize = 0.1 * size # radius of each pip hsize = size / # half of size offset = 0.6 * hsize # distance from center to outer pips # create a square for the face cx, cy = center.getX(), center.getY() p1 = Point(cx-hsize, cy-hsize) p2 = Point(cx+hsize, cy+hsize) rect = Rectangle(p1,p2) rect.draw(win) rect.setFill(self.background) # Create 7 circles for standard pip locations self.pips = [ self.__makePip(cx-offset, cy-offset), self.__makePip(cx-offset, cy), self.__makePip(cx-offset, cy+offset), self.__makePip(cx, cy), self.__makePip(cx+offset, cy-offset), self.__makePip(cx+offset, cy), self.__makePip(cx+offset, cy+offset) ] # Create a table for which pips are on for each value self.onTable = [ [], [3], [2,4], [2,3,4], [0,2,4,6], [0,2,3,4,6], [0,1,2,4,5,6] ] self.setValue(1) def __makePip(self, x, y): """Internal helper method to draw a pip at (x,y)""" pip = Circle(Point(x,y), self.psize) pip.setFill(self.background) pip.setOutline(self.background) pip.draw(self.win) return pip def setValue(self, value): """ Set this die to display value.""" # Turn all the pips off for pip in self.pips: # Turn the appropriate pips back on for i in self.onTable[value]: self.pips[i].setFill(self.foreground) Python Programming, 2/e

794 Designing with Lists and Classes
Lastly, this example showcases the advantages of encapsulation. We have improved the implementation of the dieView class, but we have not changed the set of methods it supports. We can substitute this new version of the class without having to modify any other code! Encapsulation allows us to build complex software systems as a set of “pluggable modules.” Python Programming, 2/e

795 Case Study: Python Calculator
The new dieView class shows how lists can be used effectively as instance variables of objects. Our pips list and onTable contain circles and lists, respectively, which are themselves objects. We can view a program itself as a collection of data structures (collections and objects) and a set of algorithms that operate on those data structures. Python Programming, 2/e

796 A Calculator as an Object
Let’s develop a program that implements a Python calculator. Our calculator will have buttons for The ten digits (0-9) A decimal point (.) Four operations (+,-,*,/) A few special keys ‘C’ to clear the display ‘<-’ to backspace in the display ‘=’ to do the calculation Python Programming, 2/e

797 A Calculator as an Object
Python Programming, 2/e

798 A Calculator as an Object
We can take a simple approach to performing the calculations. As buttons are pressed, they show up in the display, and are evaluated and displayed when the = is pressed. We can divide the functioning of the calculator into two parts: creating the interface and interacting with the user. Python Programming, 2/e

799 Constructing the Interface
First, we create a graphics window. The coordinates were chosen to simplify the layout of the buttons. In the last line, the window object is stored in an instance variable so that other methods can refer to it. def __init__(self): # create the window for the calculator win = GraphWin("calculator") win.setCoords(0,0,6,7) win.setBackground("slategray") self.win = win Python Programming, 2/e

800 Constructing the Interface
Our next step is to create the buttons, reusing the button class. # create list of buttons # start with all the standard sized buttons # bSpecs gives center coords and label of buttons bSpecs = [(2,1,'0'), (3,1,'.'), (1,2,'1'), (2,2,'2'), (3,2,'3'), (4,2,'+'), (5,2,'-'), (1,3,'4'), (2,3,'5'), (3,3,'6'), (4,3,'*'), (5,3,'/'), (1,4,'7'), (2,4,'8'), (3,4,'9'), (4,4,'<-'),(5,4,'C')] self.buttons = [] for cx,cy,label in bSpecs: self.buttons.append(Button(self.win,Point(cx,cy),.75,.75,label)) # create the larger = button self.buttons.append(Button(self.win, Point(4.5,1), 1.75, .75, "=")) # activate all buttons for b in self.buttons: b.activate() bspecs contains a list of button specifications, including the center point of the button and its label. Python Programming, 2/e

801 Constructing the Interface
Each specification is a tuple. A tuple looks like a list but uses ‘()’ rather than ‘[]’. Tuples are sequences that are immutable. Python Programming, 2/e

802 Constructing the Interface
Conceptually, each iteration of the loop starts with an assignment: (cx,cy,label)=<next item from bSpecs> Each item in bSpecs is also a tuple. When a tuple of variables is used on the left side of an assignment, the corresponding components of the tuple on the right side are unpacked into the variables on the left side. The first time through it’s as if we had: cx,cy,label = 2,1,”0” Python Programming, 2/e

803 Constructing the Interface
Each time through the loop, another tuple from bSpecs is unpacked into the variables in the loop heading. These values are then used to create a Button that is appended to the list of buttons. Creating the display is simple – it’s just a rectangle with some text centered on it. We need to save the text object as an instance variable so its contents can be accessed and changed. Python Programming, 2/e

804 Constructing the Interface
Here’s the code to create the display bg = Rectangle(Point(.5,5.5), Point(5.5,6.5)) bg.setFill('white') bg.draw(self.win) text = Text(Point(3,6), "") text.draw(self.win) text.setFace("courier") text.setStyle("bold") text.setSize(16) self.display = text Python Programming, 2/e

805 Processing Buttons Now that the interface is drawn, we need a method to get it running. We’ll use an event loop that waits for a button to be clicked and then processes that button. def run(self): # Infinite 'event loop' to process button clicks while True: key = self.getButton() self.processButton(key) Python Programming, 2/e

806 Processing Buttons We continue getting mouse clicks until a button is clicked. To determine whether a button has been clicked, we loop through the list of buttons and check each one. def getButton(self): # Waits for a button to be clicked and # returns the label of # the button that was clicked while True: p = self.win.getMouse() for b in self.buttons: if b.clicked(p): return b.getLabel() # method exit Python Programming, 2/e

807 Processing Buttons Having the buttons in a list like this is a big win. A for loop is used to look at each button in turn. If the clicked point p turns out to be in one of the buttons, the label of the button is returned, providing an exit from the otherwise infinite loop. Python Programming, 2/e

808 Processing Buttons The last step is to update the display of the calculator according to which button was clicked. A digit or operator is appended to the display. If key contains the label of the button, and text contains the current contents of the display, the code is: self.display.setText(text+key) Python Programming, 2/e

809 Processing Buttons The clear key blanks the display: self.display.setText("") The backspace key strips off one character: self.display.setText(text[:-1]) The equal key causes the expression to be evaluated and the result displayed. Python Programming, 2/e

810 Processing Buttons try: result = eval(text) except: result = 'ERROR' self.display.setText(str(result)) Exception handling is necessary here to catch run-time errors if the expression being evaluated isn’t a legal Python expression. If there’s an error, the program will display ERROR rather than crash. Python Programming, 2/e

811 Python Programming: An Introduction To Computer Science
Chapter 12 Object-Oriented Design Python Programming, 2/e Python Programming, 2/e

812 Objectives To understand the process of object-oriented design.
To be able to read and understand object-oriented programs. To understand the concepts of encapsulation, polymorphism and inheritance as they pertain to object-oriented design and programming. Python Programming, 2/e

813 Objectives To be able to design moderately complex software using object-oriented design. Python Programming, 2/e

814 The Process of OOD Most modern computer applications are designed using a data-centered view of computing called object-oriented design (OOD). The essence of OOD is describing a system in terms of magical black boxes and their interfaces. Python Programming, 2/e

815 The Process of OOD Each component provides a service or set of services through its interface. Other components are users or clients of the services. A client only needs to understand the interface of a service – implementation details are not important, they may be changed and shouldn’t affect the client at all! Python Programming, 2/e

816 The Process of OOD The component providing the service shouldn’t have to consider how the service is used – it just needs to provide the service “as advertised” via the interface. This separation of concerns makes the design of complex systems possible. Python Programming, 2/e

817 The Process of OOD In top-down design, functions serve the role of the black box. Client programs can use the functions as long as it understands what the function does. How the function accomplishes its task is encapsulated within the function. Python Programming, 2/e

818 The Process of OOD In OOD, the black boxes are objects.
The magic behind the objects is in the class definitions. Once a class definition is written, we can ignore how the class works and rely on the external interface, its methods. You’ve seen this when using the graphics library – you were able to draw a circle without having to know all the nitty-gritty details encapsulated in class definitions for GraphWin and Circle. Python Programming, 2/e

819 The Process of OOD Breaking a large problem into a set of cooperating classes reduces the complexity that must be considered to understand any given part of the program. Each class stands on its own! OOD is the process of finding and defining a useful set of classes for a given problem. Like design, it’s part art and part science. The more you design, the better you’ll get. Python Programming, 2/e

820 The Process of OOD Here are some guidelines for OOD:
Look for object candidates The goal is to define a set of objects that will be helpful in solving the problem. Start with a careful consideration of the problem statement – objects are usually described by nouns. Which nouns in your problem statement would be represented in your program? Which have interesting behavior or properties? Python Programming, 2/e

821 The Process of OOD Look for object candidates
Things that can be represented as primitive data types (numbers or strings) are probably not important object candidates. Things to look for: a grouping of related data items (e.g., point coordinates, employee data) Identify instance variables Once you think of some possible objects, think of the kinds of information each object will need to do its job. Python Programming, 2/e

822 The Process of OOD Identify instance variables Think about interfaces
Some object attributes will have primitive data types, while others may be complex types that suggest other useful objects/classes. Strive to find good “home” classes for all the data in your program. Think about interfaces What operations would be required for objects of that class to be useful? Consider the verbs in the problem statement. Python Programming, 2/e

823 The Process of OOD Think about interfaces
Verbs describe actions. List the methods that the class will require. Remember – all of the manipulation of the object’s data should be done through the methods you provide. Refine the nontrivial methods Some methods will probably look like they can be accomplished in a few lines of code, while others may take more programming effort. Python Programming, 2/e

824 The Process of OOD Refine the nontrivial methods
Use top-down design and stepwise refinement to flesh out the details of the more difficult methods. As you’re programming, you may discover that some new interactions with other classes are needed, and you may need to add new methods to other classes. Sometimes you may discover a need for a brand-new kind of object that calls for the definition of another class. Python Programming, 2/e

825 The Process of OOD Design iteratively
It’s not unusual to bounce back and forth between designing new classes and adding methods to existing classes. Work on whatever is demanding your attention. No one designs a program top to bottom in a linear, systematic fashion. Make progress wherever progress needs to be made. Python Programming, 2/e

826 The Process of OOD Try out alternatives
Don’t be afraid to scrap an approach that doesn’t seem to be working, or to follow an idea and see where it leads. Good design involves a lot of trial and error! When you look at the programs of others, you are looking at finished work, not the process used to get there. Well-designed programs are probably not the result of a first try. As Fred Brooks said, “Plan to throw one away.” Python Programming, 2/e

827 The Process of OOD Keep it simple
At each step in the design, try to find the simplest approach that will solve the problem. Don’t design in extra complexity until it is clear that a more complex approach is needed. Python Programming, 2/e

828 Case Study: Racquetball Simulation
You may want to review our top-down design of the racquetball simulation from Chapter 9. We want to simulate multiple games of racquetball where the ability of the two opponents is represented by the probability that they win a point when they are serving. Python Programming, 2/e

829 Case Study: Racquetball Simulation
Inputs: Probability for player A Probability for player B The number of games to simulate Output: A nicely formatted summary of the results Python Programming, 2/e

830 Case Study: Racquetball Simulation
Previously, we ended a game when one of the players reached 15 points. This time, let’s also consider shutouts. If one player gets to 7 points before the other player has scored a point, the game ends. The simulation should keep track of each players’ wins and the number of wins that are shutouts. Python Programming, 2/e

831 Candidate Objects and Methods
Our first task – find a set of objects that could be useful in solving this problem. Problem statement – “Simulate a series of racquetball games between two players and record some statistics about the series of games.” This suggests two things Simulate a game Keep track of some statistics Python Programming, 2/e

832 Candidate Objects and Methods
First, let’s simulate the game. Use an object to represent a single game of racquetball. This game will have to keep track of some information, namely, the skill levels of the two players. Let’s call this class RBallGame. Its constructor requires parameters for the probabilities of the two players. Python Programming, 2/e

833 Candidate Objects and Methods
What else do we need? We need to play the game. We can give the class a play method that simulates the game until it’s over. We could then create and play a racquetball game with two lines of code! theGame = RBallGame(probA, probB) theGame.play() Python Programming, 2/e

834 Candidate Objects and Methods
To play several games, we just need to put a loop around this code. We’ll need four counts to keep track of at least four counts to print the results of our simulation: wins for A, wins for B, shutouts for A, and shutouts for B We could also count the number of games played, but we can calculate this from the counts above. Python Programming, 2/e

835 Candidate Objects and Methods
These four related pieces of information could be grouped into a single object, which could be an instance of the class SimStats. A SimStats object will keep track of all the information about a series of games. Python Programming, 2/e

836 Candidate Objects and Methods
What operations would be useful on these statistics? The constructor should initialize the counts to 0. We need a way to update these counts while the games are simulated. How can we do this? The easiest approach would be to send the entire game object to the method and let it extract the appropriate information. Once the games are done, we need a method to print out the results – printReport. Python Programming, 2/e

837 Candidate Objects and Methods
def main(): printIntro() probA, probB, n = getInputs() # Play the games stats = SimStats() for i in range(n): theGame = RBallGame(probA, probB) # Create a new game theGame.play() # Play it stats.update(theGame) # Get info about completed game # Print the results stats.printReport() The helper functions that print an introduction and get inputs should be easy. Let’s work on the SimStats class! Python Programming, 2/e

838 Implementing SimStats
The constructor for SimStats just needs to initialize the four counts to 0. class SimStats: def __init__(self): self.winA = self.winB = self.shutsA = self.shutsB = 0 Python Programming, 2/e

839 Implementing SimStats
The update method takes a game as a parameter and updates the four counts appropriately. The heading will look like this: def update(self, aGame): We need to know the final score of the game, be we can’t directly access that information since it is an instance variable of aGame. Python Programming, 2/e

840 Implementing SimStats
We need a new method in RBallGame that will report the final score. Let’s call this new method getScores, and it will return the scores for player A and player B. Now the algorithm for update is straightforward. Python Programming, 2/e

841 Implementing SimStats
def update(self, aGame): a, b = aGame.getScores() if a > b: # A won the game self.winsA = self.winsA + 1 if b == 0: self.shutsA = self.shutsA + 1 else: # B won the game self.winsB = self.winsB + 1 if a == 0: self.shutsB = self.shutsB + 1 Python Programming, 2/e

842 Implementing SimStats
The only thing left is a method to print out the results. The method printReport will generate a table showing the wins win percentage shutouts and shutout percentage for each player. Python Programming, 2/e

843 Implementing SimStats
Here’s sample output: Summary of 500 games: wins (% total) shutouts (% wins) Player A: % % Player B: % % The headings are easy to handle, but printing the output in nice columns is harder. We also need to avoid division by 0 when calculating percentages. Python Programming, 2/e

844 Implementing SimStats
Let’s move printing the lines of the table into the method printLine. The printLine method will need the player label (A or B), number of wins and shutouts, and the total number of games (for calculating percentages). Python Programming, 2/e

845 Implementing SimStats
def printReport(self): # Print a nicely formatted report n = self.winsA + self.winsB print "Summary of", n , "games:" print print " wins (% total) shutouts (% wins) " print " " self.printLine("A", self.winsA, self.shutsA, n) self.printLine("B", self.winsB, self.shutsB, n) To finish the class, we will implement printLine. This method makes heavy use of string formatting. You may want to review string formatting in chapter ?? Python Programming, 2/e

846 Implementing SimStats
def printLine(self, label, wins, shuts, n): template = "Player %s: %4d %5.1f%% %11d %s " if wins == 0: # Avoid division by zero! shutStr = "----- " else: shutStr = "%4.1f%%" % (float(shuts)/wins*100) print template % (label, wins, float(wins)/n*100,\ shuts, shutStr) We define a template for the information that will appear in each line. The if ensures we don’t divide by 0, and the template treats it as a string. Python Programming, 2/e

847 Implementing RBallGame
This class needs a constructor that accepts two probabilities as parameters, a play method that plays the game, and a getScores method that reports the scores. Python Programming, 2/e

848 Implementing RBallGame
What will a racquetball game need to know? To play the game, we need to know The probability for each player The score for each player Which player is serving The probability and score are more related to a particular player, while the server is a property of the game between the two players. Python Programming, 2/e

849 Implementing RBallGame
So, a game needs to know who the players are The players themselves could be objects that know their probability and score and which is serving. If the players are objects, then we need a class to define their behavior. Let’s call it Player. Python Programming, 2/e

850 Implementing RBallGame
The Player object will keep track of a player’s probability and score. When a Player is initialized, the probability will be passed as a parameter. Its score will be set to 0. Let’s develop Player as we work on RBallGame. Python Programming, 2/e

851 Implementing RBallGame
The game will need instance variables for the two players, and another variable to keep track of which player has service. class RBallGame: def __init__(self, probA, probB): # Create a new game having players with the given probs self.playerA = Player(probA) self.playerB = Player(probB) self.server = self.playerA # Player A always serves first Python Programming, 2/e

852 Implementing RBallGame
Suppose we create an instance of RBallGame like this: theGame = RBallGame(.6, .5) Python Programming, 2/e

853 Implementing RBallGame
Our next step is to code how to play the game! In chapter 9 we developed an algorithm that continues to serve rallies and awards points or changes service as appropriate until the game is over. Let’s translate this algorithm into our object-based code! Python Programming, 2/e

854 Implementing RBallGame
Firstly, we need a loop that continues as long as the game is not over. The decision whether a game is over or not can only be done by looking at the game object itself. Let’s assume we have an isOver method which can be used. Python Programming, 2/e

855 Implementing RBallGame
def play(self): # Play the game to completion while not self.isOver(): Within the loop, the serving player needs to serve, and, based on the result, we decide what to do. This suggests that the Player objects should have a method that performs a serve. Python Programming, 2/e

856 Implementing RBallGame
Whether the serve is not depends on the probability stored within each player object, so, one can ask the server if the serve was won or lost! if self.server.winsServe(): Based on the result, a point is awarded or service changes. To award a point, the player’s score needs to be changed, which requires the player object to increment the score. Python Programming, 2/e

857 Implementing RBallGame
Changing servers is done at the game level, since this information is kept in the server instance variable of RBallGame. Here’s the completed play method: Python Programming, 2/e

858 Implementing RBallGame
def play(self): # Play the game to completion while not self.isOver(): if self.server.winsServe(): self.server.incScore() else: self.changeServer() Remember, self is an RBallGame! While this algorithm is simple, we need two more methods (isOver and changeServer) in the RBallGame class and two more (winServe and inScore) for the Player class. Python Programming, 2/e

859 Implementing RBallGame
Before working on these methods, let’s go back and finish the other top-level method of the RBallGame class, getScores, which returns the scores of the two players. The player objects actually know the scores, so we need a method that asks a player to return its score. Python Programming, 2/e

860 Implementing RBallGame
def getScores(self): # RETURNS the current scores of player A and player B return self.playerA.getScore(), self.playerB.getScore() This adds one more method to be implemented in the Player class! Don’t forget it!! To finish the RBallGame class, all that is needed is to write the isOver and changeServer methods (left as an exercise). Python Programming, 2/e

861 Implementing Player While developing the RBallGame class, we discovered the need for a Player class that encapsulates the service probability and current score for a player. The Player class needs a suitable constructor and methods for winsServe, incScore, and getScore. Python Programming, 2/e

862 Implementing Player In the class constructor, we need to initialize the instance variables. The probability will be passed as a variable, and the score is set to 0. def __init__(self, prob): # Create a player with this probability self.prob = prob self.score = 0 Python Programming, 2/e

863 Implementing Player To see if a player wins a serve, compare the probability of service win to a random number between 0 and 1. def winsServe(self): # RETURNS true with probability self.prob return random() <= self.prob Python Programming, 2/e

864 Implementing Player To give a player a point, we add one to the score.
def incScore(self): # Add a point to this player's score self.score = self.score + 1 The final method returns the value of the score. def getScore(self): # RETURN this player's current score return self.score Python Programming, 2/e

865 Implementing Player You may think it’s silly to create a class with many one or two-line methods. This is quite common in well-modularized, object-oriented programs. If the pieces are so simple that their implementation is obvious, we have confidence that it must be right! Python Programming, 2/e

866 The Complete Program Python Programming, 2/e # objrrball.py
# Simulation of a racquet game. # Illustrates design with objects. from random import random class Player: # A Player keeps track of service probability and score def __init__(self, prob): # Create a player with this probability self.prob = prob self.score = 0 def winsServe(self): # RETURNS true with probability self.prob return random() <= self.prob def incScore(self): # Add a point to this player's score self.score = self.score + 1 def getScore(self): # RETURN this player's current score return self.score Python Programming, 2/e

867 The Complete Program Python Programming, 2/e class RBallGame:
# A RBallGame represents a game in progress. A game as two players # and keeps track of which one is currently serving. def __init__(self, probA, probB): # Create a new game having players with the given probs. self.playerA = Player(probA) self.playerB = Player(probB) self.server = self.playerA # Player A always serves first def play(self): # Play the game to completion while not self.isOver(): if self.server.winsServe(): self.server.incScore() else: self.changeServer() def isOver(self): # RETURNS game is finished (i.e. one of the players has won). a,b = self.getScores() return a == 15 or b == 15 or \ (a == 7 and b == 0) or (b==7 and a == 0) def changeServer(self): # Switch which player is serving if self.server == self.playerA: self.server = self.playerB self.server = self.playerA def getScores(self): # RETURNS the current scores of player A and player B return self.playerA.getScore(), self.playerB.getScore() Python Programming, 2/e

868 The Complete Program Python Programming, 2/e class SimStats:
# SimStatistics handles accumulation of statistics across multiple # (completed) games. This version tracks the wins and shutouts for # each player. def __init__(self): # Create a new accumulator for a series of games self.winsA = 0 self.winsB = 0 self.shutsA = 0 self.shutsB = 0 def update(self, aGame): # Determine the outcome if aGame and update statistics a, b = aGame.getScores() if a > b: # A won the game self.winsA = self.winsA + 1 if b == 0: self.shutsA = self.shutsA + 1 else: # B won the game self.winsB = self.winsB + 1 if a == 0: self.shutsB = self.shutsB + 1 def printReport(self): # Print a nicely formatted report n = self.winsA + self.winsB print "Summary of", n , "games:" print print " wins (% total) shutouts (% wins) " print " " self.printLine("A", self.winsA, self.shutsA, n) self.printLine("B", self.winsB, self.shutsB, n) def printLine(self, label, wins, shuts, n): template = "Player %s: %4d %5.1f%% %11d %s" if wins == 0: # Avoid division by zero! shutStr = "-----" else: shutStr = "%4.1f%%" % (float(shuts)/wins*100) print template % (label, wins, float(wins)/n*100, shuts, shutStr) Python Programming, 2/e

869 The Complete Program Python Programming, 2/e def printIntro():
print "This program simulates games of racquetball between two" print 'players called "A" and "B". The ability of each player is' print "indicated by a probability (a number between 0 and 1) that" print "the player wins the point when serving. Player A always" print "has the first serve.\n" def getInputs(): # Returns the three simulation parameters a = input("What is the prob. player A wins a serve? ") b = input("What is the prob. player B wins a serve? ") n = input("How many games to simulate? ") return a, b, n def main(): printIntro() probA, probB, n = getInputs() # Play the games stats = SimStats() for i in range(n): theGame = RBallGame(probA, probB) # create a new game theGame.play() # play it stats.update(theGame) # get info about completed game # Print the results stats.printReport() Python Programming, 2/e

870 Case Study: Dice Poker Objects are very useful when designing graphical user interfaces. Let’s look at a graphical application using some of the widgets developed in previous chapters. Python Programming, 2/e

871 Program Specification
Our goal is to write a program that allows a user to play video poker using dice. The program will display a hand consisting of five dice. Python Programming, 2/e

872 Program Specification
The basic rules The player starts with $100 Each round costs $10 to play. This amount is subtracted from the user’s money at the start of the round. The player initially rolls a completely random hand (all 5 dice are rolled). The player gets two chances to enhance the hand by rerolling some or all of the dice. Python Programming, 2/e

873 Program Specification
At the end of the hand, the player’s money is updated according to the following payout schedule: Hand Pay Two Pairs 5 Three of a Kind 8 Full House (A Pair and a Three of a Kind) 12 Four of a Kind 15 Straight (1-5 or 2-6) 20 Five of a Kind 30 Python Programming, 2/e

874 Program Specification
Since we want a nice graphical interface, we will be interacting with our program through mouse clicks. The interface should have: The current score (amount of money) is constantly applied. The program automatically terminates if the player goes broke. The player may choose to quit at appropriate points during play. The interface will present visual cues to indicate what is going on at any given moment and what the valid user responses are. Python Programming, 2/e

875 Identifying Candidate Objects
The first step is to analyze the program description and identify some objects that will be useful in solving the problem. This game involves dice and money. Are they good object candidates? On their own, a single die and the money can be represented as numbers. Python Programming, 2/e

876 Identifying Candidate Objects
However, the game uses five dice, and we need to be able to roll all or a selection of the dice, as well as analyze the score. This can be encapsulated in a Dice class. Python Programming, 2/e

877 Identifying Candidate Objects
Here are some obvious operations to implement: Constructor – Create the initial collection rollAll – Assign random values to each of the five dice roll – Assign a random value to some subset of the dice, while maintaining the current value of the others. Python Programming, 2/e

878 Identifying Candidate Objects
values – Return the current values of the five dice score – Return the score for the dice The entire program can be thought of as an object. Let’s call the class PokerApp. The PokerApp object will keep track of the current amount of money, the dice, the number of rolls, etc. PokerApp will use a method called run to start the game. Python Programming, 2/e

879 Identifying Candidate Objects
Another component of the game is the user interface. A good way to break down the complexity of a more sophisticated problem is to separate the UI from the main program. This is often called the model-view approach, where the program implements some model and the interface is a view of the current state of the model. Python Programming, 2/e

880 Identifying Candidate Objects
We can encapsulate the decisions about the interface in a separate interface object. One advantage of this approach is that we can change the look and feel of the program by substituting a different interface object. Let’s call our interface object PokerInterface. Python Programming, 2/e

881 Implementing the Model
The Dice class implements a collection of dice, which are just changing numbers. The obvious representation is a list of five ints. The constructor needs to create a list and assign some initial values. Python Programming, 2/e

882 Implementing the Model
def __init__(self): self.dice = [0]* self.rollAll() This code first creates a list of five zeroes. Then they need to be set to random values. We need methods to roll selected dice and to roll all of the dice. Python Programming, 2/e

883 Implementing the Model
Since rolling all dice is a special case of rolling selected dice, we can implement the former with the latter. We can specify which dice to roll by passing a list of indexes. For example, roll([0,3,4]) will roll the dice in positions 0, 3, and 4. We can use a loop to go through the list, generating a new random value for each listed position. Python Programming, 2/e

884 Implementing the Model
def roll(self, which) for pos in which: self.dice[pos] = randint(1,6) We can use roll to implement rollAll… def rollAll(self): self.roll(range(5)) Here, range(5) is used to generate a list of all the indexes. Python Programming, 2/e

885 Implementing the Model
The values function returns the values of the dice so they can be displayed. def values(self): return self.dice[:] Why did we create a copy of the dice list by slicing it? If a Dice client modifies the list it gets back from values, it will not affect the original copy stored in the Dice object. Python Programming, 2/e

886 Implementing the Model
The score method will determine the worth of the current dice. We need to examine the values and determine whether we have any of the patterns in the table. Let’s return a string with what the hand is and an int that gives the payoff amount. Python Programming, 2/e

887 Implementing the Model
We can think of this function as a multi-way decision, checking for each possible hand. The order that we do the check is important! A full house also contains a three of a kind, but the payout should be for a full house! Python Programming, 2/e

888 Implementing the Model
One simple way to check the hand is to create a list of the counts of each value. counts[i] will be the number of times that i occurs in the roll. If the dice are [3,2,5,2,3], then the count list will be [0,0,2,2,0,1,0]. counts[0] will always be 0 since dice go from 1 – 6. Python Programming, 2/e

889 Implementing the Model
With this approach, checking for a full house entails looking for a 3 and a 2 in counts. def score(self): counts = [0] * for value in self.dice: counts[value] = counts[value] + 1 Python Programming, 2/e

890 Implementing the Model
if 5 in counts: return "Five of a Kind", elif 4 in counts: return "Four of a Kind", elif (3 in counts) and (2 in counts): return "Full House", elif (not (3 in counts)) and (not (2 in counts)) \ and (counts[1]==0 or counts[6] == 0): return "Straight", elif 3 in counts: return "Three of a Kind", elif counts.count(2) == 2: return "Two Pairs", else: return "Garbage", 0 Since we’ve already checked for 5, 4, and 3 of a kind, checking that there are no pairs -- (not (2 in counts)) guarantees that the dice show five distinct values. If there is no 6, then the values must be 1-5, and if there is no 1, the values must be 2-6. Python Programming, 2/e

891 Implementing the Model
Let’s try it out! >>> from dice import Dice >>> d = Dice() >>> d.values() [2, 3, 2, 6, 3] >>> d.score() ('Two Pairs', 5) >>> d.roll([3]) >>> d.values() [2, 3, 2, 2, 3] >>> d.score() ('Full House', 12) Python Programming, 2/e

892 Implementing the Model
We now are at the point where we can implement the poker game. We can use top-down design to flesh out the details and suggest which methods will need to be implemented in the PokerInterface class. Initially, PokerApp will need to keep track of the dice, the amount of money, and the interface. Let’s initialize these values first. Python Programming, 2/e

893 Implementing the Model
class PokerApp: def __init__(self): self.dice = Dice() self.money = self.interface = PokerInterface() To run the program, we create an instance of this class and call its run method. The program will loop, allowing the user to continue playing hands until they are either out of money or choose to quit. Python Programming, 2/e

894 Implementing the Model
Since it costs $10 to play a hand, we can continue as long as self.money >= 10. Determining whether the player wants to continue or not must come from the user interface. Python Programming, 2/e

895 Implementing the Model
def run(self): while self.money >= 10 and self.interface.wantToPlay(): self.playRound() self.interface.close() The interface.close() call at the bottom will let us do any necessary clean-up, such as printing a final message, closing graphics windows, etc. Now we’ll focus on the playRound method. Python Programming, 2/e

896 Implementing the Model
Each round consists of a series of rolls. Based on the rolls, the player’s score will be adjusted. def playRound(self): self.money = self.money – self.interface.setMoney(self.money) self.doRolls() result, score = self.dice.score() self.interface.showResult(result, score) self.money = self.money + score self.interface.setMoney(self.money) Python Programming, 2/e

897 Implementing the Model
When new information is to be presented to the user, the proper method from interface is invoked. The $10 fee to play is first deducted, and the interface is updated with the new amount of money remaining. The program processes a series of rolls (doRolls), displays the result, and updates the money. Python Programming, 2/e

898 Implementing the Model
Lastly, we need to implement the dice rolling process. Initially, all the dice are rolled. Then, we need a loop that continues rolling user-selected dice until either the user quits or the limit of three rolls is reached. rolls keeps track of how many times the dice have been rolled. Python Programming, 2/e

899 Implementing the Model
def doRolls(self): self.dice.rollAll() roll = self.interface.setDice(self.dice.values()) toRoll = self.interface.chooseDice() while roll < 3 and toRoll != []: self.dice.roll(toRoll) roll = roll self.interface.setDice(self.dice.values()) if roll < 3: toRoll = self.interface.chooseDice() Whew! We’ve completed the basic functions of our interactive poker program. We can’t test it yet because we don’t have a user interface… Python Programming, 2/e

900 A Text-Based UI In the process of designing PokerApp, we also developed a specification for a generic PokerInterface class. The interface must support methods for displaying information – setMoney setDice showResult Python Programming, 2/e

901 A Text-Based UI It also must have methods that allow input from the user – wantToPlay chooseDice These methods can be implemented in many different ways, producing programs that look quite different, even while the underlying model, PokerApp, remains the same. Python Programming, 2/e

902 A Text-Based UI Graphical interfaces are usually more complicated to build, so we might want to build a text-based interface first for testing and debugging purposes. We can tweak the PokerApp class so that the user interface is supplied as a parameter to the constructor. Python Programming, 2/e

903 A Text-Based UI def __init__(self, interface): self.dice = Dice() self.money = self.interface = interface By setting the interface up as a parameter, we can easily use different interfaces with our poker program. Here’s a bare-bones text-based interface: Python Programming, 2/e

904 A Text-Based UI # textinter.py class TextInterface: def __init__(self): print "Welcome to video poker.“ def setMoney(self, amt): print "You currently have $%d." % (amt) def setDice(self, values): print "Dice:", values def wantToPlay(self): ans = raw_input("Do you wish to try your luck? ") return ans[0] in "yY“ def close(self): print "\nThanks for playing!" Python Programming, 2/e

905 A Text-Based UI def showResult(self, msg, score): print "%s. You win $%d." % (msg,score) def chooseDice(self): return input("Enter list of which to change ([] to stop) ") Using this interface, we can test our PokerApp program. Here’s a complete program: from pokerapp import PokerApp from textinter import TextInterface inter = TextInterface() app = PokerApp(inter) app.run() Python Programming, 2/e

906 A Text-Based UI Python Programming, 2/e Welcome to video poker.
Do you wish to try your luck? y You currently have $90. Dice: [6, 4, 1, 1, 6] Enter list of which to change ([] to stop) [1] Dice: [6, 3, 1, 1, 6] Two Pairs. You win $5. You currently have $95. You currently have $85. Dice: [5, 1, 3, 6, 4] Dice: [5, 2, 3, 6, 4] Enter list of which to change ([] to stop) [] Straight. You win $20. You currently have $105. Do you wish to try your luck? n Thanks for playing! Python Programming, 2/e

907 Developing a GUI Now that we’ve verified that our program works, we can start work on the GUI user interface. This new interface will support the various methods found in the text-based version, and will likely have additional helper methods. Python Programming, 2/e

908 Developing a GUI Requirements
The faces of the dice and the current score will be continuously displayed. The setDice and setMoney methods will be used to change these displays. We have one output method, showResult. One way we can display this information is at the bottom of the window, in what is sometimes called a status bar. Python Programming, 2/e

909 Developing a GUI We can use buttons to get information from the user.
In wantToPlay, the user can choose between rolling the dice or quitting by selecting the “Roll Dice” or “Quit” buttons. To implement chooseDice, we could have a button to push for each die to be rolled. When done selecting the dice to roll, the “Roll Dice” button could be pushed. Python Programming, 2/e

910 Developing a GUI We could allow the users to change their mind on which dice to choose by having the button be a toggle that selects/unselects a particular die. This enhancement suggests that we want a way to show which dice are currently selected. We could easily “gray out” the pips on dice selected for rolling. Python Programming, 2/e

911 Developing a GUI We also need a way to indicate that we want to stop rolling and score the dice as they are. One way to do this could be by not having any selected dice and choosing “Roll Dice”. A more intuitive solution would be to add a new button called “Score”. Now that the functional aspects are decided, how should the GUI look? Python Programming, 2/e

912 Developing a GUI Python Programming, 2/e

913 Developing a GUI Our GUI makes use of buttons and dice. We can reuse our Button and DieView class from previous chapters! We’ll use a list of Buttons as we did in the calculator program in Chapter 11. The buttons of the poker interface will not be active all of the time. E.g., the dice buttons are only active when the user is choosing dice. Python Programming, 2/e

914 Developing a GUI When user input is required, the valid buttons for that interaction will be set active and the others set inactive., using a helper method called choose. The choose method takes a list of button labels as a parameter, activates them, and then waits for the user to click one of them. Python Programming, 2/e

915 Developing a GUI The return value is the label of the button that was clicked. For example, if we are waiting for the user to choose either the “Roll Dice” or “Quit” button, we could use this code: choice = self.choose(["Roll Dice", "Quit"]) if choice == ("Roll Dice"): … Python Programming, 2/e

916 Developing a GUI def choose(self, choices):
buttons = self.buttons # activate choice buttons, deactivate others for b in buttons: if b.getLabel() in choices: b.activate() else: b.deactivate() # get mouse clicks until an active button is clicked while True: p = self.win.getMouse() if b.clicked(p): return b.getLabel() Python Programming, 2/e

917 Developing a GUI The DieView class will be basically the same as we used before, but we want to add a new feature – the ability to change the color of a die to indicate when it is selected for rerolling. The DieView constructor draws a square and seven circles to represent where the pips appear. setValue turns on the appropriate pips for a given value. Python Programming, 2/e

918 Developing a GUI Here’s the setValue method as it was:
def setValue(self, value): # Turn all the pips off for pip in self.pips: pip.setFill(self.background) # Turn the appropriate pips back on for i in self.onTable[value]: self.pips[i].setFill(self.foreground) Python Programming, 2/e

919 Developing a GUI We need to modify the DieView class by adding a setColor method to change the color used for drawing the pips. In setValue, the color of the pips is determined by the value of the instance variable foreground. Python Programming, 2/e

920 Developing a GUI The algorithm for setColor seems straightforward.
Change foreground to the new color Redraw the current value of the die The second step is similar to setValue, but setValue requires the value to be sent as a parameter, and dieView doesn’t store this value anywhere. Once the pips have been turned on the value is discarded! Python Programming, 2/e

921 Developing a GUI To implement setColor, we tweak setValue so that it remembers the current value: self.value = value This line stores the value parameter in an instance variable called value. With the modification to setValue, setColor is a breeze. Python Programming, 2/e

922 Developing a GUI def setColor(self, color): self.foreground = color self.setValue(self.value) Notice how the last line calls setValue to draw the die, passing along the value from the last time setValue was called. Now that the widgets are under control, we can implement the poker GUI! The constructor will create all the widgets and set up the interface for later interactions. Python Programming, 2/e

923 Developing a GUI Python Programming, 2/e class GraphicsInterface:
def __init__(self): self.win = GraphWin("Dice Poker", 600, 400) self.win.setBackground("green3") banner = Text(Point(300,30), "Python Poker Parlor") banner.setSize(24) banner.setFill("yellow2") banner.setStyle("bold") banner.draw(self.win) self.msg = Text(Point(300,380), "Welcome to the dice table.") self.msg.setSize(18) self.msg.draw(self.win) self.createDice(Point(300,100), 75) self.buttons = [] self.addDiceButtons(Point(300,170), 75, 30) b = Button(self.win, Point(300, 230), 400, 40, "Roll Dice") self.buttons.append(b) b = Button(self.win, Point(300, 280), 150, 40, "Score") b = Button(self.win, Point(570,375), 40, 30, "Quit") self.money = Text(Point(300,325), "$100") self.money.setSize(18) self.money.draw(self.win) Python Programming, 2/e

924 Developing a GUI Did you notice that the creation of the dice and their associated buttons were moved into a couple of helper methods? def createDice(self, center, size): center.move(-3*size,0) self.dice = [] for i in range(5): view = ColorDieView(self.win, center, size) self.dice.append(view) center.move(1.5*size,0) def addDiceButtons(self, center, width, height): center.move(-3*width, 0) for i in range(1,6): label = "Die %d" % (i) b = Button(self.win, center, width, height, label) self.buttons.append(b) center.move(1.5*width, 0) center is a Point variable used to calculate the positions of the widgets. Python Programming, 2/e

925 Developing a GUI The methods setMoney and showResult display text in an interface window. Since the constructor created and positioned the Text objects, all we have to do is call setText! Similarly, the output method setDice calls the setValue method of the appropriate DieView objects in dice. Python Programming, 2/e

926 Developing a GUI def setMoney(self, amt):
self.money.setText("$%d" % (amt)) def showResult(self, msg, score): if score > 0: text = "%s! You win $%d" % (msg, score) else: text = "You rolled %s" % (msg) self.msg.setText(text) def setDice(self, values): for i in range(5): self.dice[i].setValue(values[i]) Python Programming, 2/e

927 Developing the GUI The wantToPlay method will wait for the user to click either “Roll Dice” or “Quit”. The chooser helper method can be used. def wantToPlay(self): ans = self.choose(["Roll Dice", "Quit"]) self.msg.setText("") return ans == "Roll Dice" After the user clicks a button, setting msg to "" clears out any messages. Python Programming, 2/e

928 Developing the GUI The chooseDice method is a little more complicated – it will return a list of the indexes of the dice the user wishes to roll. In our GUI, the user chooses dice by clicking on the corresponding button. We need to maintain a list of selected buttons. Python Programming, 2/e

929 Developing a GUI Each time a button is clicked, that die is either chosen (its index appended to the list) or unchosen (its index removed from the list). The color of the corresponding dieView will then reflect the current status of the dice. Python Programming, 2/e

930 Developing a GUI Python Programming, 2/e def chooseDice(self):
# choices is a list of the indexes of the selected dice choices = [] # No dice chosen yet while True: # Wait for user to click a valid button b = self.choose(["Die 1", "Die 2", "Die 3", "Die 4", "Die 5", "Roll Dice", "Score"]) if b[0] == "D": # User clicked a die button i = eval(b[4]) # Translate label to die index if i in choices: # Currently selected, unselect it choices.remove(i) self.dice[i].setColor("black") else: # Currently unselected, select it choices.append(i) self.dice[i].setColor("gray") else: # User clicked Roll or Score for d in self.dice: # Revert appearance of all dice d.setColor("black") if b == "Score": # Score clicked, ignore choices return [] elif choices != []: # Don't accept Roll unless some return choices # dice are actually selected Python Programming, 2/e

931 Developing a GUI The only missing piece of our interface class is the close method. To close the graphical version, we just need to close the graphics window. def close(self): self.win.close() Python Programming, 2/e

932 Developing a GUI Lastly, we need a few lines to get the graphical poker playing program started! We use GraphicsInterface in place of TextInterface. inter = GraphicsInterface() app = PokerApp(inter) app.run() Python Programming, 2/e

933 OO Concepts The OO approach helps us to produce complex software that is more reliable and cost-effective. OO is comprised of three principles: Encapsulation Polymorphism Inheritance Python Programming, 2/e

934 Encapsulation As you’ll recall, objects know stuff and do stuff, combining data and operations. This packaging of data with a set of operations that can be performed on the data is called encapsulation. Encapsulation provides a convenient way to compose complex problems that corresponds to our intuitive view of how the world works. Python Programming, 2/e

935 Encapsulation From a design standpoint, encapsulation separates the concerns of “what” vs. “how”. The implementation of an object is independent of its use. The implementation can change, but as long as the interface is preserved, the object will not break. Encapsulation allows us to isolate major design decisions, especially ones subject to change. Python Programming, 2/e

936 Encapsulation Another advantage is that it promotes code reuse. It allows us to package up general components that can be used from one program to the next. The DieView and Button classes are good examples of this. Encapsulation alone makes a system object-based. To be object-oriented, we must also have the properties of polymorphism and inheritance. Python Programming, 2/e

937 Polymorphism Literally, polymorphism means “many forms.”
When used in object-oriented literature, this refers to the fact that what an object does in response to a message (a method call) depends on the type or class of the object. Python Programming, 2/e

938 Polymorphism Our poker program illustrated one aspect of this by the PokerApp class being used with both TextInterface and GraphicsInterface. When PokerApp called the showDice method, the TextInterface showed the dice one way and the GraphicsInterface did it another way. Python Programming, 2/e

939 Polymorphism With polymorphism, a given line in a program may invoke a completely different method from one moment to the next. Suppose you had a list of graphics objects to draw on the screen – a mixture of Circle, Rectangle, Polygon, etc. Python Programming, 2/e

940 Polymorphism You could draw all the items with this simple code: for obj in objects: obj.draw(win) What operation does this loop really execute? When obj is a circle, it executes the draw method from the circle class, etc. Python Programming, 2/e

941 Polymorphism Polymorphism gives object-oriented systems the flexibility for each object to perform an action just the way that it should be performed for that object. Python Programming, 2/e

942 Inheritance The idea behind inheritance is that a new class can be defined to borrow behavior from another class. The new class (the one doing the borrowing) is called a subclass, and the other (the one being borrowed from) is called a superclass. This is an idea our examples have not included. Python Programming, 2/e

943 Inheritance Say we’re building an employee management system.
We might have a class called Employee that contains general information common to all employees. There might be a method called homeAddress that returns an employee’s home address. Python Programming, 2/e

944 Inheritance Within the class of employees, we might distinguish between salaried and hourly employees with SalariedEmployee and HourlyEmployee, respectively. Each of these two classes would be a subclass of Employee, and would share the homeAddress method. Python Programming, 2/e

945 Inheritance Each subclass could have its own monthlyPay function, since pay is computed differently for each class of employee. Inheritance has two benefits: We can structure the classes of a system to avoid duplication of operations, e.g. there is one homeAddress method for HourlyEmployee and SalariedEmployee. New classes can be based on existing classes, promoting code reuse. Python Programming, 2/e

946 Inheritance We could have used inheritance to build the DieView class.
Our first DieView class did not provide a way to change the appearance of the dir. Rather than modifying the original class definition, we could have left the original alone and created a new subclass called ColorDieView. Python Programming, 2/e

947 Inheritance A ColorDieView is just like DieView, except it has an additional method! class ColorDieView(DieView): def setValue(self, value): self.value = value DieView.setValue(self, value) def setColor(self, color): self.foreground = color self.setValue(self.value) Python Programming, 2/e

948 Inheritance The first line (class ColorDieView(DieView): ) says that we are defining a new class ColorDieView that is based on (i.e. is a subclass of) DieView. Inside the new class we define two methods. The second method, setColor, adds the new operation. To make it work, setValue also needed to be slightly modified. Python Programming, 2/e

949 Inheritance The setValue method in ColorDieView redefines or overrides the definition of setValue that was provided in the DieView class. The setValue method in the new class first stores the value and then relies on the setValue method of the superclass DieView to actually draw the pips. Python Programming, 2/e

950 Inheritance The normal approach to set the value, self.setValue(value), would refer to the setValue method of the ColorDieView class, since self is an instance of ColorDieView. To call the superclass’s setValue method, it’s necessary to put the class name where the object would normally go: DieView.setValue(self,value) Python Programming, 2/e

951 Inheritance DieView.setValue(self,value)
The actual object to which the method is applied is sent as the first parameter. Python Programming, 2/e


Download ppt "Python Programming: An Introduction to Computer Science"

Similar presentations


Ads by Google