object-oriented programming in python goldwasser and letscher chapter 5 additional control...
Post on 21-Dec-2015
232 views
TRANSCRIPT
Object-Oriented Programming in PythonGoldwasser and Letscher
Chapter 5Additional Control Structures
Terry Scott
University of Northern Colorado2007 Prentice Hall
2
Introduction: Chapter 5 Topics
• While loop.
– compare with for loop.
– infinite loop.
• Function.
– parts of function: call, heading, body, parameters.
– optional parameters.
• Avoiding duplicate code.
• Case study: Computing the square root.
• Error checking and exceptions.
• Case Study: Simulating a chain under force of gravity.
3
While Loop
• More flexible than for loop.while condition: body
• Example:ans=raw_input('Shall we play a game? ')while answer.lower() in ('y', 'yes'): #code for playing game ans= raw_input('Would you like to play again? ')
5
Finding the Greatest Common Divisor
u = input('Enter the first number: ')
v= input('Enter the second number: ')
guess=min(u,v)
while u% guess > 0 or v%guess > 0:
guess -= 1
print 'The gcd is', guess
6
Finding the Greatest Common Denominator (Euclid's Algorithm)
#more efficient than previous algorithm.
u = input('Enter the first number: ')
v= input('Enter the second number: ')
while v != 0:
r = u % v
u = v
v = r
print 'The gcd is', u
7
Checking whether an element is in a list
• Using for loop:found = Falsefor item in data: if item == val:
found = True
• This is inefficient since once val is found it continues to search.
• Can use break statement to exit loop once item is found.
8
Searching a List (continued)
#Using a while loop is more efficient
#Once val is found the loop is exited.
i = 0
found = False
while i<len(data) and not found:
if data[i] == val:
found = True
else:
i+= 1
9
Reading Data from the User:First Try
#must read name twiceguests = [ ]name=raw_input('Enter name: ')while name: #an empty string is False
guests.append(name) name=raw_input('Enter name: ')
print 'You entered', len(guests), 'guests.'
10
Reading Data from the User: Second Try
#an empty string is False
guests = [ ]
name='fake' #this primes the loop
while name:
name=raw_input('Enter name: ')
if name: #only add to list if not empty
guests.append(name)
print 'You entered', len(guests), 'guests.'
11
Reading Data from the UserThird Try
#an empty string is False
guests = [ ]
name='fake'#this primes the loop
while name:
name=raw_input('Enter name: ')
guests.append(name)
guests.pop() #remove last empty string
print 'You entered', len(guests), 'guests.'
12
Verifying Input Using a While Loop
ans = raw_input('Continue? (y/n): ')
while not ans in ('y', 'n'):
print 'Response must be y or n'
ans = raw_input('Continue? (y/n): ')
13
Infinite Loops
• for loops are automatically bounded by the number of times they execute.
• while loops are not automatically bounded, execution may become stuck in the loop. The following example is likely never to actually occur.
while True:
print 'Hello'
14
Infinite Loops (continued)
• Most infinite loops are more subtle than the previous one.
• In the code below i is never incremented. Unless val is the first item, the loop won't end.
i = 0
found = False
while i < len(data) and not found:
if data[i] == val:
found = True
15
Functions: Another Control Structure
• Calling a function: power(3,2)
• Implementation– heading: def power(base, power)– parameters:
• formal parameters: base and power• actual parameters: 3, 2
– body: return 3 ** 2
16
Calling a Function
ingredients = 'carbonated water', 'caramel color', 'phosphoric acid', 'sodium saccharin', 'caffeine', 'potassium benzoate', 'aspartame', 'citric acid', 'potassium citrate', 'aspartame', 'natural flavors', 'dimethylpolysiloxane']
concern = maxLength(ingredients) #function call
print concern
17
Parameter Passing
• The list is named ingredients at the call to the function. It is called stringSeq at the function definition.
18
Function Definition: Find Maximum Length of Strings.
def maxLength(stringSeq): longSoFar = "" #null string – nothing between two double quotes for entry in stringSeq: if len(entry) > len(longSoFar): longSoFar = entry return longSoFar
ingredients = 'carbonated water', 'caramel color', 'caffeine', 'phosphoric acid', 'sodium saccharin', 'potassium benzoate', 'aspartame', 'potassium citrate', 'citric acid', 'dimethylpolysiloxane', 'natural flavors']
concern = maxLength(ingredients)print concernOutput: dimethylpolysiloxane
19
Return Value
• The function return value is called longSoFar and is called concern at the call to the function
21
Nested Function Calls
• A called function can call other functions.
• Diagram shows flow of control.
22
Optional Parameters
def countdown(start = 10):
for count in range(start, 0, -1)
print count
countdown() #will countdown starting at 10
countdown(5) #will countdown starting at 5
23
Flow of Control
• The default is to have statements be executed in the order they appear, sometimes called sequencing.
• To change the order of execution from sequencing, use flow of control statements:– if, if-else, if-elif-. . . else– for– while– function
24
Avoiding Duplicate Code
print 'I will not chew gum in class'
#copy and paste 100 times
#A better way to do this is the following
for i in range(100):
print 'I will not chew gum in class'
25
Duplicate Code:Example
from time import sleeptimeDelay = 25car.move(-10,0)sleep(timeDelay)car.move(-30,0)sleep(timeDelay)car.move(-60,0)sleep(timeDelay)car.move(-100,0)sleep(timeDelay)
26
Avoiding Duplicated Code: Better Than Code on Previous Slide
# Better than previous slide
from time import sleep
timeDelay = .25
for deltaX in (-10, -30, -60, -100)
car.move(deltaX, 0)
sleep(timeDelay)
27
Using a Function to Avoid Duplication
• Drawing three circles as was done in Chapter 3 for the target.
• Could write code to do each one of the circles.
• Better: Write a function that can be called three times with different parameters.
28
Using a Function to Eliminate Repeated Code
def createRing(radius, color, depth):
c = Circle(radius)
c.setFillColor(color)
c.setDepth(depth)
return c
#call function three times.
target.add(createRing(30, 'white', 49)
target.add(createRing(20, 'blue', 48)
target.add(createRing(10, 'red', 47)
29
Conditional Statements with Duplicate Code.
#this has duplicate code
if destination == 'Missouri':
subtotal = sum(shoppingCart)
tax = subtotal * 0.04225
total = subtotal + tax
elif destination == 'Illinois':
subtotal = sum(shoppingCart)
tax = subtotal * 0.0625
total = subtotal + tax
30
Conditional Statements: Better than Previous slide
subtotal = sum(shoppingCart)
if destination == 'Missouri':
tax = subtotal * 0.04225
elif destination == 'Illinois':
tax = subtotal * 0.0625
total = subtotal + tax
31
Conditional Statements (Avoiding Duplicate Code)
# To improve readability call a function to
# lookup tax rates.subtotal = sum(shoppingCart)
tax = subtotal * lookupTaxRate(destination)
total = subtotal + tax
32
Computing Square Root: poor
#Does not always work. Gets stuck in infinite
#loop
def sqrtA(number):
guess = 1.0
while guess != number / guess:
guess = (guess + number / guess)/2.0
return guess
33
Computing Square Root: Good
#Fixed number of iterations
def sqrtB(number):
guess = 1.0
for trial in range(100):
guess = (guess + number / guess)/2.0
return guess
34
Computing the Square Root: Better
#Iterate until gap is small.
def sqrtC(number, Error=.000001):
guess = 1.0
while abs(guess-number/guess) > Error:
guess = (guess + number / guess)/2.0
return guess
35
Computing the Square Root: Best
#Best: Iterate until no more improvement
def sqrtD(number):
prevGuess = 0.0
guess = min(1.0, number)
while prevGuess < guess:
prevGuess = guess
avg = (guess+number/guess)/2.0
guess = min(avg, number/avg)
return guess
36
Exceptions: How to Deal with Error Situations
number = 0
while not 1 <= number <= 10:
try:
number= int(raw_input('Enter number from 1 to 10: '))
if not 1 <= number <= 10:
print 'Your number must be from 1 to 10:'
except ValueError:
print 'That is not a valid integer.'
37
Exceptions (continued)
• What if a negative is entered for square root?
• Can raise an exception when something unusual occurs.
def sqrE(number): if number < 0: raise ValueError('number must be positive') #do square root code as before
38
Exceptions (continued)
#What if value entered is not a number?
def sqrtF(number):
if not isinstance(number, (int, float)):
raise TypeError('number must be numeric')
if number < 0:
raise ValueError('number must be positive')
#do square root code as before
39
How Much Type Checking is Enough?
• A function with little type checking of its parameters may be difficult to diagnose errors.
• A function with much type checking of its parameters will be harder to write and consume more time executing.
• If the function is one that only you will use you may need less type checking.
• A function written for others should have more type checking.
41
Three Forces Acting on Each Link
• Force from left chain link.• Force down from gravity.• Force from right chain link.
43
Case Study:Simulating a Chain at Equilibrium
Under the Force of Gravity• Forces on each link are:
– the link to its left.– the link to its right.– gravity downward.
• As with other programs break the code down into functions:
#adding two or three tuples together.def combine(A, B, C = (0,0)): return (A[0]+B[0]+C[0], A[1]+B[1]+C[1])
44
Chain in Equilibrium (continued)
def calcForce(A,B):dX = B[0] – A[0]dY = B[1] – A[1]distance = sqrt(dX*dX + dY*dY)if distance > restingLength:
stretch = distance – restingLengthforceFactor = stretch*elasticityConstant
else:forceFactor = 0
return (forceFactor*dX, forceFactor*dY)
45
Chain in Equilibrium (continued)#continue to compute until movement is less than epsilon.somethingMoved = Truewhile somethingMoved: somethingMoved = False oldChain = list(chain) # a new list for k in range(1, numLinks):
gravForce = (0, gravityConstant) leftForce = calcForce(oldChain[k], oldChain[k-1]) rightForce = calcForce(oldChain[k], oldChain[k+1]) adjust = combine(leftForce, rightForce, gravForce) if abs(adjust[0]) > epsilon or abs(adjust[1]) > epsilon:
somethingMoved = True chain[k] = combine(oldChain[k], adjust)
46
Adding Graphics to Chain
paper=Canvas(totalSeparation,totalSeparation)
#many points to plot so make refresh manual
paper.setAutoRefresh(False)
curve = Path()
for p in chain:
curve.addPoint(Point(p[0], p[1]))
paper.add(curve)
47
Adding Graphics to Chain (continue)
# function to alter the graphical path and
# refresh canvas
def drawChain(chainData, chainPath, theCanvas):
for k in range(len(chainData)):
chainPath.setPoint(Point(chainData[k][0], chainData[k][1]),k)
theCanvas.refresh()