3.3.1. Simple while Loops¶Other than the trick with using a Show
Presumably you would test your tea. If it were too hot, you would add a little ice. If you test again and it is still too hot, you would add ice again. As long as you tested and found it was true that your tea was too hot, you would go back and add more ice. Python has a similar syntax:
Setting up the English example in a similar format would be:
To make things concrete and numerical, suppose the following: The tea starts at 115 degrees Fahrenheit. You want it at 112 degrees. A chip of ice turns out to lower the temperature one degree each time. You test the temperature each time, and also print out the temperature before reducing the temperature. In Python you could write and run the code below, saved in example program cool.py:
I added a final line after the while loop to remind you that execution follows sequentially after a loop completes. If you play computer and follow the path of execution, you could generate the following table. Remember, that each time you reach the end of the indented block after the
Each time the end of the indented loop body is reached, execution returns to the A
Test yourself: Following the code. Figure out what is printed. : i = 4 while i < 9: print(i) i = i+2 Check yourself by running the example program Note In Python, Predict what will happen with this slight variation on the previous example, switching the order in the loop body. Follow it carefully, one step at a time.
Check yourself by running the example program The sequence order is important. The variable
Predict what happens in this related little program: nums = list() i = 4 while (i < 9): nums.append(i) i = i+2 print(nums) Check yourself by running the example program 3.3.2. The Most General range Function¶There is actually a much simpler way to generate the previous
sequences like in nums = range(4, 9, 2) print(list(nums)) The third parameter for the range function is the step size. It is needed when the step size from one element to the next is not 1. The most general syntax is
The value of the second parameter is always past the final element of the list. Each element after the first in the list is step more than the previous one. Predict and try in the Shell: Actually the range function is even more sophisticated than indicated by the Do you see how 0 is past the end of the list? Try it: Make up a These ranges, like the simpler ranges that we used earlier, are most often used as the sequence in a for i in range(10, 0, -1): # countdown... print(i) print('Blastoff!') 3.3.3. Interactive while Loops¶The earlier examples of while loops were chosen for their simplicity. Obviously they could have been rewritten with range function calls. Now lets try a more interesting example. Suppose you want to let a user enter a sequence of lines of text, and want to remember each line in a list. This could easily be done with a simple
repeat loop if you knew the number of lines to enter. For example, in lines = list() n = int(input('How many lines do you want to enter? ')) for i in range(n): line = input('Next line: ') lines.append(line) print('Your lines were:') # check now for line in lines: print(line) The user may want to enter a bunch of lines and not count them all ahead of time. This means the number of repetitions would not be known ahead of time. A lines = list() testAnswer = input('Press y if you want to enter more lines: ') while testAnswer == 'y': line = input('Next line: ') lines.append(line) testAnswer = input('Press y if you want to enter more lines: ') print('Your lines were:') for line in lines: print(line) See the two statements setting Note The data must be initialized before the loop, in order for the first test of the while condition to work. Also the test must work when you loop back from the end of the loop body. This means the data for the test must also be set up a second time, in the loop body (commonly as the action in the last line of the loop). It is easy to forget the second time! The What should the while condition be now? Since the sentinel is an empty line, you might think
Of course in this situation there is a shorter way, Run the example program lines = list() print('Enter lines of text.') print('Enter an empty line to quit.') line = input('Next line: ') # initalize before the loop while line != '': # while NOT the termination condition lines.append(line) line = input('Next line: ') # !! reset value at end of loop! print('Your lines were:') for line in lines: print(line) Again the data for the test in the while loop heading must be initialized before the first time
the After reading the rest of this paragraph, comment the last line of the loop out, and run it again: It will never stop! The variable Note As you finish coding a The earliest Some of the exercises that follow involve interactive while loops. Others were delayed until here just because they have a wider variety of continuation condition tests and ways to prepare for the next time through the loop. What is consistent is the general steps to think of and questions to ask yourself. They keep on applying! Keep these in mind!
Detecting the need for 3.3.3.1. Interactive Sum Exercise¶Write a program 3.3.3.2. Safe Number Input Exercise¶* There is an issue with reading in numbers with the input statement. If you make a typo and enter something that cannot be converted from a string to the right kind of number, a naive program will bomb. This is avoidable if you test the string and repeat if the string is illegal. In this exercise write safe utility function replacements for the input function that work to read in a whole number, an integer or a decimal number. All parts refer to the previous Is Number String Exercise. Part a. refers to the introduction in the previous exercise. Parts b. and c. refer to functions in the solution, Save the example
3.3.3.3. Savings Exercise¶The idea here is to see how many years it will take a bank account to grow to at least a given value, assuming a fixed annual interest. Write a program All the monetary amounts that you print should be rounded to exactly two decimal places. Start by printing the initial balance this way. For example, if the initial balance was entered as 123.5, it should be reprinted by your program as 123.50. Also print the balance each year until the desired amount is reached or passed. The first balance at or past the target should be the last one printed. The math: The amount next year is the amount now times (1 + interest fraction), so if I have $500 now and the interest rate is .04, I have $500*(1.04) = $520 after one year and after two years I have, $520*(1.04) = $540.80.... For example, if I respond to the prompts, and enter into the program a $500 starting balance, .04 interest rate and a target of $550, the program prints: 500.00 520.00 540.80 562.43 3.3.3.4. Strange Sequence Exercise¶* Recall Strange Function Exercise and its You can start with one number, say n = 3, and keep applying the jump function to the last number given, and see how the numbers jump around! jump(3) = 3*3+1 = 10; jump(10) = 10//2 = 5; jump(5) = 3*5+1 = 16; jump(16) = 16//2 = 8; jump(8) = 8//2 = 4; jump(4) = 4//2 = 2; jump(2) = 2//2 = 1 This process of repeatedly applying the same function to the most recent result is called function iteration. In this case you see that iterating the jump function, starting from n=3, eventually reaches the value 1. It is an open research question whether iterating the jump function from an integer n will eventually reach 1, for every starting integer n greater than 1. Researchers have only found examples of n where it is true. Still, no general argument has been made to apply to the infinite number of possible starting integers. In this exercise you iterate the jump function for specific starting values n, until the result is 1.
3.3.4. Graphical Applications¶Another place where a Creating a polygon is a unified activity with a clear result, so let’s define a function. It involves a boundary rectangle and mouse clicks in a GraphWin, and may as well return the Polygon constructed. Read the following start: def polyHere(rect, win): ''' Draw a polygon interactively in Rectangle rect, in GraphWin win. Collect mouse clicks inside rect into the vertices of a Polygon, and always draw the Polygon created so far. When a click goes outside rect, stop and return the final polygon. The Polygon ends up drawn. The method draws and undraws rect. ''' It is useful to start by thinking of the objects needed, and give them names.
Certainly the overall process will be repetitious, choosing point after point. Still it may not be at all clear how to make an effective Python loop. In challenging situations like this it is often useful to imagine a concrete situation with a limited number of steps, so each step can be written in sequence without worrying about a loop. For instance to get up to a triangle (3 vertices in our list and a fourth mouse click for the sentinel), you might imagine the following sequence, undrawing each old polygon before the next is displayed with the latest mouse click included: rect.setOutline('red') rect.draw(win) vertices = list() pt = win.getMouse() vertices.append(pt) poly = Polygon(vertices) poly.draw(win) # with one point pt = win.getMouse() poly.undraw() # missing latest point vertices.append(pt) poly = Polygon(vertices) poly.draw(win) # with two points pt = win.getMouse() poly.undraw() # missing latest point vertices.append(pt) poly = Polygon(vertices) poly.draw(win) # with three points pt = win.getMouse() # assume outside the region rect.undraw() return poly There is a fine point here that I missed the first time. The vertices of an existing Polygon do not get mutated in this system. A new Polygon gets created each time with the new vertex list. The old Polygon does not go away automatically, and extraneous lines appear in the picture if the old polygon is not explicitly undrawn each
time before a new version is redrawn with an extra vertex. The last Polygon you draw should be visible at the end, so in the example above where I was assuming the third click was the last for the triangle, I did not The timing for each If you think of the repetitions through a large number of loops, the process is essentially circular (as suggested by the word ‘loop’). The body of a loop in Python, however, is written as a linear sequence: one with a first line and a last line, a beginning and an end. We can cut a circular loop anywhere to get a piece with a beginning and an end. In practice, the place you cut the loop for Python has one
main constraint: The processing in Python from the end of one time through the loop to the beginning of the next loop is separated by the test of the condition in the heading. The continuation condition in the It can help to look at a concrete example sequence, like the steps listed above for creating a triangle, only now assuming we do not know how many
vertices will be chosen. The continuation condition is for while isInside(pt, rect): With this condition in mind, look for where to split to loop. It needs to be after a new while isInside(pt, rect): vertices.append(pt) poly = Polygon(vertices) poly.draw(win) pt = win.getMouse() poly.undraw() If you follow the total sequence of required steps above for making the concrete triangle, you see that this
full sequence for the loop is only repeated twice. The last time there is no There are several possible approaches. You want the
if isInside(pt, rect): poly.undraw() I find this option unaesthetic: it means duplicating the continuation test twice in every loop. Instead of avoiding the If you look at the overall concrete sequence for the triangle, not all the lines are in the loop. You must carefully include the lines both that come before the loop and those that come after the loop. Make sure these lines are not put in the loop, but before or after, as indicated by the concrete sequence in the example. In the end the entire function is: def polyHere(rect, win): ''' Draw a polygon interactively in Rectangle rect, in GraphWin win. Collect mouse clicks inside rect into the vertices of a Polygon, and always draw the Polygon created so far. When a click goes outside rect, stop and return the final polygon. The Polygon ends up drawn. The method draws and undraws rect. ''' rect.setOutline("red") rect.draw(win) vertices = list() pt = win.getMouse() while isInside(pt, rect): vertices.append(pt) poly = Polygon(vertices) poly.draw(win) pt = win.getMouse() poly.undraw() poly.draw(win) rect.undraw() return poly Make sure you understand: Follow this code through, imagining three mouse clicks inside rect and then one click outside of rect. Compare the steps to the ones in the concrete sequence written out above and see that the match (aside from
the last canceling This function is illustrated in the example program rect1 = Rectangle(Point(5, 55), Point(200, 120)) poly1 = polyHere(rect1, win) poly1.setFill('green') rect2 = Rectangle(Point(210, 50), Point(350, 350)) poly2 = polyHere(rect2, win) poly2.setOutline('orange') As you can see, the returned polygons are used to make color changes, just as an illustration. In earlier animation examples a In full-fledged graphical systems that respond to events, this is no problem. Zelle’s graphics is built on top of a capable event-driven system, and in fact, all mouse clicks are
registered, even outside calls to As an example, run example program Aside from the prompts, the difference from the previous by the following initialization and while loop heading: while win.checkMouse() == None: #NEW* The graphics module remembers the last mouse click, whether or not it occurred during a call to
The A similar elaboration can be made for the other examples of animation, like In The program includes a new utility function to help determine the initial (dx, dy) for the animation. This is done by calculating the move necessary to go from one point (where the ball is in this program) to another (specified by a user’s mouse click in this program). : def getShift(point1, point2): # NEW utility function '''Returns a tuple (dx, dy) which is the shift from point1 to point2.''' dx = point2.getX() - point1.getX() dy = point2.getY() - point1.getY() return (dx, dy) Since the function calculates both a change in x and y, it returns a A straightforward interactive method, def getUserShift(point, prompt, win): #NEW direction selection '''Return the change in position from the point to a mouse click in win. First display the prompt string under point.''' text = Text(Point(point.getX(), 60), prompt) text.draw(win) userPt = win.getMouse() text.undraw() return getShift(point, userPt) In the new version of the main driver, center = Point(win.getWidth()/2, win.getHeight()/2) #NEW central starting point ball = makeDisk(center, radius, win) #NEW interactive direction and speed setting prompt = ''' Click to indicate the direction and speed of the ball: The further you click from the ball, the faster it starts.''' (dx, dy) = getUserShift(center, prompt, win) scale = 0.01 # to reduce the size of animation steps bounceInBox(ball, dx*scale, dy*scale, xLow, xHigh, yLow, yHigh, win) The You can look in Idle at the full source code for In the examples so far of the use of This version only slightly modifies the central animation function,
def bounceInBox(shape, dx, dy, xLow, xHigh, yLow, yHigh, win): ''' Animate a shape moving in jumps (dx, dy), bouncing when its center reaches the low and high x and y coordinates. The animation stops when the mouse is clicked, and the last mouse click is returned.''' delay = .001 pt = None #NEW while pt == None: #NEW shape.move(dx, dy) center = shape.getCenter() x = center.getX() y = center.getY() isInside = True #NEW if x < xLow or x > xHigh: dx = -dx isInside = False #NEW if y < yLow or y > yHigh: dy = -dy isInside = False #NEW time.sleep(delay) if isInside: # NEW don't mess with dx, dy when outside pt = win.checkMouse() #NEW return pt #NEW def moveInBox(shape, stopHeight, xLow, xHigh, yLow, yHigh, win): #NEW '''Shape bounces in win so its center stays within the low and high x and y coordinates, and changes direction based on mouse clicks, terminating when there is a click above stopHeight.''' scale = 0.01 pt = shape.getCenter() # starts motionless while pt.getY() < stopHeight: (dx, dy) = getShift(shape.getCenter(), pt) pt = bounceInBox(shape, dx*scale, dy*scale, xLow, xHigh, yLow, yHigh, win) def makeDisk(center, radius, win): '''Return a red disk that is drawn in win with given center and radius.''' disk = Circle(center, radius) disk.setOutline("red") disk.setFill("red") disk.draw(win) return disk def getShift(point1, point2): '''Returns a tuple (dx, dy) which is the shift from point1 to point2.''' dx = point2.getX() - point1.getX() dy = point2.getY() - point1.getY() return (dx, dy) def bounceBall(): '''Make a ball bounce around the screen, and react to mouse clicks.''' win = GraphWin('Ball Bounce 3', 290, 290) win.yUp() #NEW to mark and label the area where a click stops the program lineHeight = win.getHeight() - 40 textHeight = win.getHeight() - 20 Line(Point(0, lineHeight), Point(win.getWidth(), lineHeight)).draw(win) prompt = 'Click above the line to stop\nor below to move toward the click.' Text(Point(win.getWidth()/2, textHeight), prompt).draw(win) radius = 10 xLow = radius # center is separated from the wall by the radius at a bounce xHigh = win.getWidth() - radius yLow = radius yHigh = lineHeight - radius #NEW lower top to bouncing limits center = Point(win.getWidth()/2, lineHeight/2) ball = makeDisk(center, radius, win) moveInBox(ball, lineHeight, xLow, xHigh, yLow, yHigh, win) #NEW win.close() bounceBall() I initially made only the changes discussed so far (not the ones involving the new variable Each time the mouse is clicked, the ball is to switch
direction and move toward the last click, until the stopping condition occurs, when there is a click above the stop line. This is clearly repetitive and needs a while loop. The condition is simply to test the y coordinate of the mouse click against the the height of the stop line. The body of the loop is very short, since we already have the utility function def moveInBox(shape, stopHeight, xLow, xHigh, yLow, yHigh, win): #NEW '''Shape bounces in win so its center stays within the low and high x and y coordinates, and changes direction based on mouse clicks, terminating when there is a click above stopHeight.''' scale = 0.01 pt = shape.getCenter() # starts motionless while pt.getY() < stopHeight: (dx, dy) = getShift(shape.getCenter(), pt) pt = bounceInBox(shape, dx*scale, dy*scale, xLow, xHigh, yLow, yHigh, win) The variable I occasionally detected a bug when using the program. The ball would get stuck just outside the boundary and stay there. The fact that it was slightly beyond the boundary was a clue: For simplicity I had cheated, and allowed the ball to go just one animation step beyond the intended boundary. With the speed and small step size this works visually. The original code was sure to make an opposite jump back inside at the next step. After some thought, I noticed that the initial version of the bounce3.py code for Neither of the original boundary-checking 3.3.4.1. Exercise Moving Undraw¶** As discussed above at
Where to split the loop, the basic loop logic works whether the 3.3.4.2. Make Path Exercise¶** Write a program that is outwardly very similar to In your main program, call the 3.3.4.3. Random Start Exercise¶* (Optional) I chose to have the ball start motionless, by making the initial
value of 3.3.4.4. Mad Lib While Exercise¶** Write
a program Hints: This is actually the most natural approach. I avoided 3.3.4.5. Find Hole Game Exercise¶** Write a graphical game program, Hint: you have already seen the code to determine the displacement (dx, dy) between two points: use the Many elaborations on this game are possible! Have fun with it! 3.3.5. Fancier Animation Loop Logic (Optional)¶The final variation is the example program def moveInBox(shape, stopHeight, xLow, xHigh, yLow, yHigh, win): ''' Animate a shape moving toward any mouse click below stopHeight and bouncing when its center reaches the low or high x or y coordinates. The animation stops when the mouse is clicked at stopHeight or above.''' scale = 0.01 delay = .001 dx = 0 #NEW dx and dy are no longer parameters dy = 0 #NEW while True: #NEW exit loop at return statement center = shape.getCenter() x = center.getX() y = center.getY() isInside = True if x < xLow or x > xHigh: dx = -dx isInside = False if y < yLow or y > yHigh: dy = -dy isInside = False if isInside: pt = win.checkMouse() if pt != None: #NEW dealing with mouse click now here if pt.getY() < stopHeight: # switch direction (dx, dy) = getShift(center, pt) (dx, dy) = (dx*scale, dy*scale) else: #NEW exit from depths of the loop return #NEW shape.move(dx, dy) time.sleep(delay) Recall that a
How do you do a for loop descending in Python?To reverse for loop in Python just need to read the last element first and then the last but one and so on till the element is at index 0. You can do it with the range function, List Comprehension, or reversed() function.
How do you sort a list in Python while loop?ALGORITHM:. STEP 1: Declare and initialize an array.. STEP 2: Loop through the array and select an element.. STEP 3: The inner loop will be used to compare the selected element from the outer loop with the rest of the elements of the array.. STEP 4: If any element is less than the selected element then swap the values.. How do I print numbers from 1 to 10 in Python?# Python program to print numbers from n to 1.. number = int ( input ( "Please Enter any Number: " )) i = number.. while ( i > = 1 ):. print (i, end = ' ' ) i = i - 1.. Can range go backwards Python?But Python does have a built-in reversed function. If you wrap range() inside reversed() , then you can print the integers in reverse order. range() makes it possible to iterate over a decrementing sequence of numbers, whereas reversed() is generally used to loop over a sequence in reverse order.
|