Discussion 1: Introduction to Python

So you want to code in Python? We will do some basic manipulations and demonstrate some of the basics of the notebook interface that we will be using extensively throughout the course.

Topics:

  • Math
  • Variables
  • Lists
  • Control flow
  • Coding style
  • Other data structures
  • IPython/Jupyter notebooks

Other intros:

Python Math

Lets start with some basic functions:


In [1]:
2 + 2


Out[1]:
4

In [2]:
32 - (4 + 2)**2


Out[2]:
-4

In [3]:
1 / 2


Out[3]:
0

Why do we get the answer above rather than what we would expect?

The answer has to do with the type of number being used. Python is a "dynamically" typed language and automatically determines what kind of number to allocate for us. Above, because we did not include a decimal, Python automatically treated the expression as integers (int type) and according to integer arithmetic, 1 / 2 = 0. Now if we include a decimal we get:


In [4]:
1.0 / 2


Out[4]:
0.5

Note that Python will make the output a float in this case. What happens for the following though?


In [5]:
4.0 + 4**(3/2)


Out[5]:
8.0

In [6]:
4.0 + 4.0**(3.0 / 2.0)


Out[6]:
12.0

Good practice to just add a decimal after any number you really want to treat as a float.

Additional types of numbers include complex, Decimal and Fraction.


In [1]:
3+5j


Out[1]:
(3+5j)

Note that to use "named" functions such as sqrt or sin we need to import a module so that we have access to those functions. When you import a module (or package) in Python we are asking Python to go look for the code that is named and make them active in our workspace (also called a namespace in more general parlance). Here is an example where we use Python's builtin math module:


In [3]:
import math
math.sqrt(4)


Out[3]:
2.0

In [4]:
math.sin(math.pi / 2.0)


Out[4]:
1.0

In [5]:
math.exp(-math.pi / 4.0)


Out[5]:
0.45593812776599624

Note that in order to access these functions we need to prepend the math. to the functions and the constant $\pi$. We can forgo this and import all of what math holds if we do the following:


In [6]:
from math import *
sin(pi / 2.0)


Out[6]:
1.0

Note that many of these functions always return a float number regardless of their input.

Variables

Assign variables like you would in any other language:


In [8]:
num_students = 80
room_capacity = 85
(room_capacity - num_students) / room_capacity * 100.0


Out[8]:
0.0

Note that we do not get what we expect from this expression as we expected from above. What would we have to change to get this to work?

We could go back to change our initializations but we could also use the function float to force these values to be of float type:


In [9]:
float(room_capacity - num_students) / float(room_capacity) * 100.0


Out[9]:
5.88235294117647

Note here we have left the defined variables as integers as it makes sense that they remain that way (fractional students aside).


In [10]:
a = 10
b = a + 2
print b


12

Lists

One of the most useful data structures in Python is the list.


In [11]:
grades = [90.0, 67.0, 85.0, 76.0, 98.0, 70.0]

Lists are defined with square brackets and delineated by commas. Note that there is another data type called sequences denoted by ( ) which are immutable (cannot be changed) once created. Lets try to do some list manipulations with our list of grades above.

Access a single value in a list


In [12]:
grades[3]


Out[12]:
76.0

Note that Python is 0 indexed, i.e. the first value in the list is accessed by 0.

Find the length of a list


In [13]:
len(grades)


Out[13]:
6

Add values to a list


In [14]:
grades = grades + [62.0, 82.0, 59.0]
print grades


[90.0, 67.0, 85.0, 76.0, 98.0, 70.0, 62.0, 82.0, 59.0]

Slicing is another important operation


In [15]:
grades[2:5]


Out[15]:
[85.0, 76.0, 98.0]

In [16]:
grades[0:4]


Out[16]:
[90.0, 67.0, 85.0, 76.0]

In [17]:
grades[:4]


Out[17]:
[90.0, 67.0, 85.0, 76.0]

In [18]:
grades[4:]


Out[18]:
[98.0, 70.0, 62.0, 82.0, 59.0]

Note that the range of values does not include the last indexed! This is important to remember for more than lists but we will get to that later.


In [19]:
grades[4:11]


Out[19]:
[98.0, 70.0, 62.0, 82.0, 59.0]

Another property of lists is that you can put different types in them at the same time. This can be important to remember if you may have both int and float types.


In [20]:
remember = ["2", 2, 2.0]

In [21]:
remember[0] / 1


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-21-32cb4b753c65> in <module>()
----> 1 remember[0] / 1

TypeError: unsupported operand type(s) for /: 'str' and 'int'

In [22]:
remember[1] / 1


Out[22]:
2

In [23]:
remember[2] / 1


Out[23]:
2.0

Finally, one of the more useful list creation functions is range which creates a list with the bounds requested


In [24]:
count = range(3,7)
print count


[3, 4, 5, 6]

Control Flow

if

Most basic logical control


In [25]:
x = 4
if x > 5:
    print "x is greater than 5"
elif x < 5:
    print "x is less than 5"
else:
    print "x is equal to 5"


x is less than 5

for

The for statements provide the most common type of loops in Python (there is also a while construct).


In [26]:
for i in range(5):
    print i


0
1
2
3
4

In [27]:
for i in range(3,7):
    print i


3
4
5
6

In [28]:
for animal in ['cat', 'dog', 'chinchilla']:
    print animal


cat
dog
chinchilla

Related to the for statement are the control statements break and continue. Ideally we can create a loop with logic that can avoid these but sometimes code can be more readable with judiciuos use of these statements.


In [29]:
for n in range(2, 10):
    is_prime = True
    for x in range(2, n):
        if n % x == 0:
            print n, 'equals', x, '*', n / x
            is_prime = False
            break
    if is_prime:
        print "%s is a prime number" % (n)


2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

The pass statement might appear fairly useless as it simply does nothing but can provide a stub to remember to come back and implement something


In [30]:
def my_func(x):
    # Remember to implement this later!
    pass

Defining Functions

The last statement above defines a function in Python with an argument called x. Functions can be defined and do lots of different things, here are a few examples.


In [31]:
def my_print_function(x):
    print x

my_print_function(3)


3

In [32]:
def my_add_function(a, b):
    return a + b

my_add_function(3.0, 5.0)


Out[32]:
8.0

In [33]:
def my_crazy_function(a, b, c=1.0):
    d = a + b**c
    return d

my_crazy_function(2.0, 3.0), my_crazy_function(2.0, 3.0, 2.0), my_crazy_function(2.0, 3.0, c=2.0)


Out[33]:
(5.0, 11.0, 11.0)

In [34]:
def my_other_function(a, b, c=1.0):
    return a + b, a + b**c, a + b**(3.0 / 7.0)

my_other_function(2.0, 3.0, c=2.0)


Out[34]:
(5.0, 11.0, 3.601328885557697)

Lets try writing a bit more of a complex (and useful) function. The Fibinocci sequence is formed by adding the previous two numbers of the sequence to get the next value (starting with [0, 1]).


In [35]:
def fibonacci(n):
    """Return a list of the Fibonacci sequence up to n"""
    values = [0, 1]
    while values[-1] <= n:
        values.append(values[-1] + values[-2])
    return values

fibonacci(100)


Out[35]:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

Coding Style

Very important in practice to write readable and understandable code. Here are a few things to keep in mind while programming in and out of this class, we will work on this actively as the semester progresses as well. The standard for which Python program are written to is called PEP 8 and contains the following basic guidelines:

  • Use 4-space indentation, no tabs
  • Wrap lines that exceed 80 characters
  • Use judicious use of blank lines to separate out functions, classes, and larger blocks of contained code
  • Comment! Also, put comments on their own line when possible
  • Use docstrings (function descriptions)
  • Use spaces around operators and after commas, a= f(1, 2) + g(3, 4)
  • Name your classes and functions consistently.
    • Use CamelCase for classes
    • Use lower_case_with_underscores for functions and variables
  • When in doubt be verbose with your comments and names of variables, functions, and classes

To help all of us learn from each other what coding styles are easier to read we will be doing peer-reviews of the coding portions of the assignments. After the first asssignment is turned in we will review a general template for code review which you will need to fill out for each of your peer's homework. Please be as thorough and helpful as you can!

IPython/Jupyter Notebooks

We will use a lot of IPython/Jupyter notebooks in this class for both class notes (what you are looking at now) and for turning in homework. The IPython notebook allows for the inline inclusion of a number of different types of input, the most critical will be

  • Code (python or otherwise) and
  • Markdown which includes
    • LaTeX,
    • HTML, and
    • JavaScript. IPython notebooks allow us to organize and comment on our efforts together along with writing active documents that can be modified in-situ to our work. This can lead to better practice of important ideas such as reproducibility in our work.