Lecture 3

Objectives for today

  1. Use standard modules like math, random, and turtle
  2. Describe aspects of good coding style, including named constants
  3. Use a for loop to iterate through a range

Reminders

  1. The most important readings each week are the Prelab and Lab write-ups (this week: Prelab 2 and Lab 2)
  2. You can submit to Gradescope as often as you like before the deadline (only the last submission will be graded)
  3. Fill out the Engaged Listening Survey you got in email
  4. Prelab 2 is due on Friday at the beginning of lab. On Friday we will start with a quiz and then work on Lab 2 in class.
  5. For help: ASIs (every afternoon), peer tutoring (every evening in 75 SHS 224)

Modules

Python provides many modules of functionality that can be imported and reused (Python’s tag line is “Batteries included”). For Lab 2 we will use the math module, random module, and turtle module.

You can import these modules a number of different ways, e.g.,

# Import turtle functions etc. with `t.` prefix
import turtle as t

# Shorthand for import turtle as turtle
import turtle

# Import all functions directly into current symbol table, i.e. with no prefix
from random import *

# Import specific functions
from math import pow, sqrt

Why might you choose one approach over the other? It is trade-off between convenience (typing shorter names) and the possibility of naming conflicts. By using the namespace prefix (i.e., the full module name) we prevent namespace conflicts, but may have to type more.

Good coding practice

In writing Python code, we generally aim to follow the PEP-8 Python style guidelines.

Review the notes on comments and docstrings.

Constants

We use named constants in code for fixed values that should be available throughout our program and do not change. By convention, we use all capital letters for constants, as opposed to lowercase letters for variables.

Consider the following function for the Lorentz factor by which time changes for an object with relativistic velocity (apologies to the physicists among us).

def lorentz(velocity):
    return 1 / (1 - (velocity ** 2) / (300000000 ** 2)) ** 0.5

What is 300000000? Does that change? We’re using it here as an approximation to the speed of light in meters per second. A better practice is to define a named constant and use that, e.g.,

SPEED_OF_LIGHT=300000000
def lorentz(velocity):
    return 1 / (1 - (velocity ** 2) / (SPEED_OF_LIGHT ** 2)) ** 0.5

This SPEED_OF_LIGHT defintion is just an approximation. A more accurate definition would be

SPEED_OF_LIGHT=299792458

Having this one definition at the top of our program means that we can use the constant SPEED_OF_LIGHT instead of typing 299792458 every time we want to use this value. If we didn’t use a constant we would need to change every use of 300000000 in our code.

So in general we use constants to improve readability, ease making changes, and help us be more consistent. There are many places in Lab 2 where you should use constants.

Note that Python doesn’t enforce (like some other languages do) that SPEED_OF_LIGHT is actually constant. Instead it is a convention. You can change the value, but shouldn’t.

Organization of our files

We will try to organize our files in the same order. This makes it easier for us (and other programmers) to read our code because they know exactly where to look for module imports, constants, etc.

In general we aim for:

  1. Docstring describing the file (in our case name, section, assignment, etc.)
  2. Module imports
  3. Constant definitions
  4. Function definitions

For example, here is a code segment that imports a module, defines a constant, and then defines a function:

import math

SPEED_OF_LIGHT=299792458

def lorentz(velocity):
    return 1 / math.sqrt(1 - (math.pow(velocity,2) / math.pow(SPEED_OF_LIGHT, 2)))

Turtle

In the lab this week we are going to use the turtle module. turtle mimics an old programming language Logo.

import turtle as t

Recall this makes available all functions in the turtle module, accessible with the prefix t.

turtle works by moving a “pen” around the screen, e.g.,

def draw_square():
    t.forward(100)
    t.right(90)
    t.forward(100)
    t.right(90)
    t.forward(100)
    t.right(90)
    t.forward(100)
    t.right(90)

Warning about turtle gotchas

  1. Make sure you never name a program turtle.py; if you do, the turtle module can’t be imported, and you can’t draw with the turtle.
  2. After drawing with the turtle, you may need to restart the Python console by clicking the Stop sign icon. (The graphics system that underlies turtle can only be “fired” once per Python console session.)

for loops

The for loop gives us a mechanism for running code a specified number of times.

Note that the code above repeats the lines

    t.forward(100)
    t.right(90)

four times. We can improve definition of draw_square with a for loop that performs this pair of lines four times. We can also generalize the code by converting from a fixed side length to a function parameter that we can change.

def draw_square_with_loop(side_length):
    for i in range(4):
        t.forward(side_length)
        t.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 generally:

  1. Defines a loop variable that is set each iteration. For indexes, the convention is to use i, j, and k although you can and should use more descriptive variable names when relevant.
  2. The loop variable is set from some sequence. In this case the range function generates a sequence of integers starting at 0 up to but not including the supplied stop parameter, i.e., in this case 0, 1, 2, 3. So there will be 4 iterations. As we will see in future classes there are other kinds of sequences.
  3. Each iteration the loop variable is set to the next value from the sequence and the for-loop body is executed.

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:

  1. Before the loop
  2. Inside the loop body
  3. After the 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.

Peer instruction questions (For loops) [1] (Section A, Section B)

Recall in the first lecture 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.

Here are several simple turtle examples for you to review in preparation for lab.

Summary

  1. Modules
  2. Constants
  3. Turtle
  4. Basic for loops