Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download

LS30 Cookbook

Views: 6814

Python

- lists, srange and zip - if/else/elif - for/while loops - functions

Lists

Lists are an ordered collection of "things". In programming parlance, we call these "things" elements. In the example below, my_list is just a list of numbers, arranged in order. Each number is a seperate element of the list.

my_list = [3,1,5,3,6,4,7] # creates a list.
my_list[0] # gets the FIRST item in the list. Python is a language that starts indexing from 0.
3
my_list[1] # gets the second item in the list.
1
my_list[6] # gets the seventh item in the list.
7
my_list[-1] # another way to get the last item in the list.
7
len(my_list) # returns the length of the list.
7

You may want to create a list yourself. For small lists, it is easy to just write them down yourself. For longer lists, it can be very tedious to do so. In this case, you should use the srange function. Its syntax is like this:

srange(start, stop, step_size)
  • start is the number to start counting at.

  • stop is the number to stop counting at. The list will increment up until one before this number.

  • step_size is the increment to increase by.

srange(0,5,1) # steps counts from 0 to 4. Notice that there are 5 elements in total.
[0, 1, 2, 3, 4]
srange(0,5,2) # steps up in steps of 2.
[0, 2, 4]
srange(0,5,0.5) # can use non-integer steps
[0.000000000000000, 0.500000000000000, 1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, 3.00000000000000, 3.50000000000000, 4.00000000000000, 4.50000000000000]
srange(-3,5) # you can leave out the last argument; the default step-size is 1.
[-3, -2, -1, 0, 1, 2, 3, 4]
srange(5) # if you only supply one argument, start=0 and step_size=1.
[0, 1, 2, 3, 4]

Zip

Frequently, you'll need to join two or more lists together. (This happens a lot when making lists of coordinates for list_plot) You can use the zip function to do this.

people = ['sam','stef','aisha','tim','maret'] age = [20, 19, 18, 13, 21] zip(people, age)
[('sam', 20), ('stef', 19), ('aisha', 18), ('tim', 13), ('maret', 21)]

See how the people and ages got matched up together? That's how to use zip. Very commonly, you'll use this to help plot lists of data to make a timeseries or a trajectory. For example, we'll plot the function f(x)=x2f(x) = x^2 for the values x=0...20 x = 0 ... 20

time_data = srange(20) position_data = [x^2 for x in time_data] # squares all of the time data list_plot(zip(time_data, position_data), figsize=3)

if/else/elif

This is a way of making decisions. The if keyword evaluates a boolean statement and returns either True or False. If the statement returns True the body of the if statement is evaluated. Otherwise (else) the program moves on to the next block.

Boolean operators

  • < less than

  • > greater than

  • <= less than or equal to

  • >= greater than or equal to

  • == equivalent

  • != not equivalent

  • and logical AND

  • or logical OR

  • not changes False to True and vice versa

5-3 equals 2
# if/else statement If True, evaluate block under if, otherwise evaluate block under else. random_number = RR.random_element(-1,1) # picks random number between -1 and 1 print "random number = {}".format(random_number) if random_number > 0: print 'larger than zero' else: print 'smaller than zero'
random number = -0.189215887880844 smaller than zero
# if/elif/else: evaluate multiple conditions random_number = RR.random_element(0,3) print "random number = {}".format(random_number) if random_number >= 0 and random_number < 1: print '0 <= x < 1' elif random_number >= 1 and random_number <2: print '1 <= x < 2' else: print '2 <= x < 3'
random number = 0.0957526245896377 0 <= x < 1

For/While Loops

  • for

    • relationship with srange/range

    • use of zip to iterate through multiple arguments

  • while

  • break

A common idiom in programming languages instructs the computer to do something repeatedly, for a specific number of times. In plain english, an instruction to do this might look like the following:

for each item in this collection of things: do something with this item then go on to the next one

In Python, we do this with a for loop. Here is its syntax:

for <item> in <list, dict or something else that can be iterated over>: # do something with <item>

As always, examples are often the most instructive.

# a simple example for i in [1,2,3]: print i print "loop finished"
1 2 3 loop finished

Here's how this for loop works:

  1. The for loop begins on line 1. It will iterate through (go through) a list that contains the elements 1,2 and 3.

  2. i is set to 1, the first element of the list.

  3. The body of the for loop is executed. The value of i (1) is printed. (note that it is indented)

  4. i is set to 2, the second element of the list.

  5. The body of the for loop is executed. The value of i (2) is printed.

  6. i is set to 3, the third element of the list.

  7. The body of the for loop is executed. The value of i (3) is printed.

  8. We're at the end of the list, so the for loop ends and we continue execution at line 3.

  9. "loop finished" is printed.

Notice that line 2 is indented to denote the code that will be repeated during the for loop and line 3 is not indented, indicating that it is not part of the for loop.

It is really common to want to iterate through a list of numbers, but it would take a really long time to create a list that long. Let's use the function srange, which can create that list for us. srange(3) returns the list [0,1,2] (three elements)

for i in srange(3): # prints 0, 1 and 2 print i print "loop finished"
0 1 2 loop finished

There's times when you will want to iterate through multiple variables at the same time. You can do this by iterating through a list of tuples. You can use the zip function to help you do this. This example shows how to use the rainbow function to color each plot with a different color.

# plot sin(i*x) with i = 1,2 and 3 and have different colors for each var('x') num_list = srange(1,4) for i, c in zip(num_list, rainbow(len(num_list))): # i=[1,2,3], c=[hex codes for red, green and blue] p = plot(sin(i*x), color=c) show(p, figsize=4)
x

Working on data by looping through it and appending it to another list is a very common task, common enough for its own recipe.

my_data = [1,3,5,3,4] # replace with whatever data you need to manipulate new_data = [] # create empty list to hold results for d in my_data: data = d + 1 new_data.append(data) my_data new_data # new data has my_data with 1 added to every element.

Nested for loops

It's common to need to iterate through a particular list while also going through a separate list in order to get all of the combinations of the elements of those two (or more lists). Here's an example of that that will print out the multiplication tables for all of the numbers from 1-5:

for i in srange(1,6): for j in srange(1,6): print "{:3d}".format(i*j), # a little bit of fancy formatting to pad the numbers print
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25

Notice how i is incremented in the outer loop while j is incremented in the inner loop. Try keeping track of the variables and tracing through the code to see how this works.

While Loops

while loops are closely related to for loops. They allow you to do something repeatedly while a condition is met. The syntax is relatively simple:

while <boolean statement>: # do something here

In the example below, we use a while loop to print out the numbers 0-2 by incrementing a variable each time we go through the loop.

# basic while loop i = 0 while i < 3: print i i = i + 1 print 'finished the loop' print i
0 1 2 finished the loop 3

Functions

Functions are typically used when you have some code that you either

  1. want to use repeatedly in multiple places

  2. want to use similar code with very slight modifications

Functions can help make your code more readable and split it up into sections that are convenient to use, test and reason about. In python, functions are defined with the def keyword and are followed by the name of the function and then its arguments. Here is an example of a function named say that takes one argument, something_to_say, and prints out whatever is given to it. Note that just like if/else statements and for/while loops, functions use indented blocks to delineate what code is part of the function.

def say(something_to_say): print something_to_say # indented block say("hello") # always make sure to test functions after creating them. Nothing will be printed out if this line is commented out.
hello

How to write a function

When considering how to write a function, it often helps to follow a series of steps.

  1. Think about what your function's purpose is. Decide on a name for the function that describes its purpose.

  2. Think about what inputs (if any) your function requires and what outputs (if any) it should return.

  3. Consider how you expect to use your function. Write that expected use case down.

  4. In plain english, write down a step-by-step recipe for what your function should do. Programmers often call this pseudocode. Try tracing through it by hand and confirm that it *probably* does what you expect it to do. This will help you catch logic errors.

  5. Fill out the pseduocode that you wrote down before with actual code, testing the intermediate results along the way if possible.

  6. Use the expected use case that you wrote before to test your function. Does it produce the expected result?

For example, I want to write a function called multiply that will multiply the two numbers a and b.

Its inputs should be two numbers a and b and it should return their product, a*b.

I expect to use my function like this:

a = 5 b = 6 multiply(a,b)

Its inputs and outputs will probably look something like this:

def multiply(a,b): ... return product

Use the test case that you wrote earlier to examine the output of your function for errors.

def multiply(a,b): product = a*b return product a = 5 b = 6 multiply(a,b) # looks like things are working alright.
30

From Script to Function (from Jane Shevtsov)

Despite all the abbreviation, iterating a function using the code you developed often means copying and modifying a hefty chunk of code. The kind of program you have, which consists of a series of commands for performing a particular task, is called a script. It’s often useful to turn a script into a function that can work for different inputs.

Here are some steps meant to be used as a guide for turning your own scripts into functions.

  1. Make sure you know exactly what you want the function to accomplish. Write this as a comment at the top of your code.

  2. Identify the output the function will need to return. Write this as a comment.

  3. Identify the inputs that the function will need. These will be the arguments that the function takes. Write them as another comment.

  4. Come up with a name for the function that briefly describes what it does. Write the function header. This is the def my_function_name(input1, input2, ...): line that goes at the beginning of the function.

  5. Copy and paste your script below the function header, as the body of the function, and indent it as necessary.

  6. Copy your comment describing the function output and paste it near the end of the function, where you expect to put the return statement.

  7. Put in the return statement to output whatever the function needs to output.

  8. Delete any statements in the body of the function that explicitly supply data that will now be given as an input (argument) to the function. Change any references to this data so that they now refer to the correct function input (argument).

  9. Go through your code and find any places where you used particular features of an example, such as the length of a list or the number of times a process should be repeated. Change them so they either (1) use the appropriate function inputs (arguments), or (2) calculate the necessary value as the function runs.

  10. Test your function on the original example. When that works correctly, test your function on other examples by calling it with different inputs. Remember, the whole point of a function is that it should give the correct output for any inputs you give it, without you having to change the actual function code each time. All you should have to do is change the inputs when you “call” the function.

  11. Remember, mistakes are expected, and programmers at all levels make them. The skills you learn in finding and fixing your mistakes should serve you well in other fields.

Immutable and Mutable objects in python

Integers, floats, strings, booleans and tuples are immutable objects. list, dict and matrices (among other things) are mutable objects. In python, unlike many other programming languages (like C), assigning a variable to an object (ie var = 5) simply assigns the name var to represent that object instead of copying it. For immutable objects, there is usually no confusion.

a = 1 b = a # b is a reference to the immutable value 1 b = 5 # b is now a reference to the immutable value 5 print a, b, "no difference between a and b" a = "this is an immutable string" b = a b = "this is another immutable string" print "a = {}".format(a) print "b = {}".format(b)
1 5 no difference between a and b a = this is an immutable string b = this is another immutable string
# tuples are a list-like object that cannot be changed. A = (1,2,3,4) B = A # B is a reference to A; not a copy B[2] = 5 # tuples are immutable; you can't change them
Error in lines 3-3 Traceback (most recent call last): File "/cocalc/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 1044, in execute exec compile(block+'\n', '', 'single', flags=compile_flags) in namespace, locals File "", line 1, in <module> TypeError: 'tuple' object does not support item assignment

However, mutable objects like lists and matrices often just change the referenced object instead of copying. This can lead to some really unexpected behavior. Thus, assigning a list/matrix to a variable name just makes that name a reference to that list/matrix instead of actually copying the object.

To get around this, you should use the copy() function to make a copy of the object that will not reference the original.

A = [1,2,3,4] B = A # B is a reference to A; not a copy B[2] = 5 # since A and B are both references to the same list, changing the list pointed to by B also changes the list pointed to by A print "A = {}".format(A) print "B = {}".format(B)
A = [1, 2, 5, 4] B = [1, 2, 5, 4]
A.sort() print "A = {}".format(A) # A is sorted print "B = {}".format(B) # B is **also** sorted
A = [1, 2, 4, 5] B = [1, 2, 4, 5]
C = copy(A) C[0] = 99 print "A = {}".format(A) print "B = {}".format(B) print "C = {}".format(C) # C is changed without modifying A or B
A = [1, 2, 4, 5] B = [1, 2, 4, 5] C = [99, 2, 4, 5]

Matrices are also mutable objects.

A = matrix([[1,2],[3,4]]) B = A # B is a reference to A; not a copy B[0,0] = 5 # since A and B are both references to the same matrix, changing the matrix pointed to by B also changes the matrix pointed to by A show( "A =" ,A) show( "B =", B)
A = (5234)\displaystyle \left(\begin{array}{rr} 5 & 2 \\ 3 & 4 \end{array}\right)
B = (5234)\displaystyle \left(\begin{array}{rr} 5 & 2 \\ 3 & 4 \end{array}\right)
C = copy(A) C[0,0] = 99 show( "A =" ,A) show( "B =", B) show( "C =", C) # C is changed without modifying A or B
A = (5234)\displaystyle \left(\begin{array}{rr} 5 & 2 \\ 3 & 4 \end{array}\right)
B = (5234)\displaystyle \left(\begin{array}{rr} 5 & 2 \\ 3 & 4 \end{array}\right)
C = (99234)\displaystyle \left(\begin{array}{rr} 99 & 2 \\ 3 & 4 \end{array}\right)