In the lab this week we are going to use the
mimics an old programming language Logo (Logo was actually my first
from turtle import *
Recall that this imports all the functions, etc. from the
turtle module into our
turtle works by moving a “pen” around the screen, e.g.
def draw_square(): forward(100) right(90) forward(100) right(90) forward(100) right(90) forward(100) right(90)
That repetition is very tedious (and not very DRY). We know we want to move and
turn 4 times. Can we loop over those statements 4 times? Yes. With a
for loop does exactly what it sounds like. For a specific set of
iterations, execute the statements in the body. Note that we also convert that
fixed side length into function parameter that we can change (making our function more flexible and useful).
def draw_square_with_loop(side_length): for i in range(4): forward(side_length) right(90)
Note that “for” and “in” are reserved words (just like
def) and therefore
they cannot be used as variable or function names.
A for-loop in Python generally:
kalthough you can and should use more descriptive variable names when relevant.
rangefunction generates a sequence of integers starting at 0 up to but not including the supplied stop parameter (and exclusive end), e.g. 0, 1, 2, 3. So there will be 4 iterations. As we will see in future classes there are other kinds of sequences.
Let’s look at another example using loops, this time to print numbers:
def print_loop(n): """ Print numbers from 0 until (but not including) n """ print("Begin list of numbers") for i in range(n): print(i) print("End list of numbers")
>>> print_loop(5) Begin list of numbers 0 1 2 3 4 End list of numbers
We can use the above output to remind us that there are three “regions” in and around our loop:
The statements inside the loop body will execute on every loop iteration, while the “after” statements will only execute once and only after all of the loop iterations are complete.
PI Questions (For loops)1
Recall in the first class that we said the computers were the right tool for the job when we needed to do something more than once. As you might imagine for-loops are one of our key tools for doing anything more than once. For example, when performing a computation “for each” data point in a file, or simulating a process “for” a set of different inputs.
forloops and scope
We saw that functions create a new scope, that is variables defined in a
function are not visible outside that function. Do
for loops similarly create
a new scope? No. For simplicity, the designers of Python decided that only
modules, classes (which we will learn about later) and functions will create a new
scope. Thus the loop variable and any variables we define inside the loop body
will be visible from that point to the end of the function, module, etc..
You may encounter errors with turtle, including rendering again after a
call or closing the drawing window. The graphics system that underlies turtle
can only be “fired” once per Python console session. You can restart the Python
console by clicking the Stop sign icon.
We saw that we can control the direction and angle of the drawing pen. What
else can we control to enhance our square? Lets check out the
docs. Here we change the
color of the line to be red and set the color of the interior of our square to
be yellow. The key for the “fill” is invoking
begin_fill before you draw the
shape and then
end_fill after you draw the shape.
pencolor("red") fillcolor("yellow") begin_fill() draw_square_with_loop(100) end_fill()
What about more interesting shapes? Specifically a Fibonacci
spiral. A Fibonacci spiral is
created by inscribing quarter circles inside squares whose edge length
increases as the Fibonacci sequence. Let’s implement a function
that has two parameters, the starting radius of the spiral and the number
segments, and draws a Fibonacci spiral.
We can do so with a three step process:
turtlefor drawing portions of a circle
Try it out before peeking at the code.
def golden_spiral(radius, segments): """ Draw a Fibonacci spiral using Turtle. turtle package must be imported into namespace. Args: radius: Starting radius of the spiral segments: Number of quarter circle segments to draw after initial quarter circle. Must be >= 2. Returns: None """ a = radius circle(a, 90) b = radius circle(b, 90) # range can take two arguments, start and stop. We set the start at two since the first two # segments are already drawn for i in range(2, segments): c = a + b circle(c, 90) # Prepare for the next iteration of the loop a = b b = c
Note that if we invoke the
golden_spiral function several times, each new
spiral starts from where the last one finished. This reminds us that the pen
has “state”, specifically an x and y position and a heading. Controlling that
state is a key part of the upcoming lab. How could we control where the drawing starts?
That is how could we modify our function to have the following definition and start drawing the spiral at a specific location on the screen?
def golden_spiral(x, y, radius, segments):
We need a way move the pen around the page. If we review the
docs, we that there is a
sounds like it will do exactly what we want. If we try that out in the shell, e.g.
>>> setpos(100, 100)
we notice that every time we move the pen it draws a line. If we think about how we
would draw this picture (with pen and paper), we would pick our hand up from
the page before moving. Again returning to the docs, we see there is a function
picking the pen up and thus not drawing while moving. With those pieces we can
now enhance our
golden_spiral function to start drawing at an arbitrary
def golden_spiral(x, y, radius, segments): penup() setpos(x, y) pendown() # Need to put the pendown to start drawing again ...
Recall that pen (turtle) also has a heading that you will need to control in a similar way. I suspect you might find similar code at the beginning of several of your functions. If you we find ourselves with repeated code, we can often DRY it up with a function.
Here are many more turtle examples for you to review in preparation for lab.