Please, rename this notebook before editing!

The Programming Language Python

Introduction

Python is meant to be a simple, readable high-level language that is easily extensible. Well-written python code should be easy for a collaborator to understand, provided they have a good grasp of the python language.

One of the pitfalls of python is that whitespace matters. In a for/while/if statement, the relevant lines must be indented. This is good for readability, but can cause some hard-to-catch debugging errors!

Python uses dynamic typing. This means that you don't have to declare your variables and types like in C/C++/Java; but that does not mean that you can stop thinking about type. For example, a=3 sets a to an integer (int), while and a=3.0 (or a=3.) makes it a floating-point number (float). Ints and floats are treated differently; for example, in python 2.7, b=3/5 will set b to 0, while b=3./5. will set it to 0.6!

You may find python somewhat quirky to use. Don't worry, you will get used to it, and you will find that it is a very flexible and powerful tool to have.

References

Here are some references to freshen up on concepts:

Python 2 vs Python 3

While there are a number of major differences between the versions the majority of libraries and tools that we are concerned with operate on both. Most changes in Python 3 concern the internal workings and performance. Though, there are some syntax changes, and some operations behave differently. This pages offers a comprehensive look at the key changes: http://sebastianraschka.com/Articles/2014_python_2_3_key_diff.html

We provide both versions on our cluster: the binaries python and python2 for Python 2.7, and python3 for version 3.4.

All assignments are expected to run on Python 2.7

The following has been adopted from https://www.learnpython.org/

Variables and Types

One of the conveniences and pit-falls is that Python does not require to explicitly declare variables before using them. This is common in many other programming languages. Python is not statically typed, but rather follows the object oriented paradigm. Every variable in Python is an object.

However, the values that variables hold have a designated data type.

This tutorial will go over a few basic types of variables.

Numbers

Python supports two types of numbers - integers and floating point numbers. Basic arithmetic operations yield different results for integers and floats. Special attention needs to be given when mixing values of different types within expressions the results might be unexpected.

To define an integer, use the following syntax:


In [48]:
myint = 7
print myint
print type(myint)


7
<type 'int'>

To define a floating point number, you may use one of the following notations:


In [49]:
myfloat = 7.0
print myfloat, type(myfloat)
myfloat = float(42)
print myfloat, type(myfloat)


7.0 <type 'float'>
42.0 <type 'float'>

In [53]:
print 7/2
print 7./2


3
3.5

Arithmetic operations

We can arithmetic operations that are common in many programing languages.

  • +, -, *, /
  • // is a special integer division even if the operands aren't
  • x**y is used for $x^y$
  • n % k calculates the remainder (modulo) of the integer division of n by k

Try it out!


In [54]:
import math as ma

In [55]:
ma.log10(100)


Out[55]:
2.0

In [56]:
(numerator, denominator) = 3.5.as_integer_ratio()
print numerator, denominator, numerator/denominator, float(numerator)/float(denominator)


7 2 3 3.5

In [4]:



Out[4]:
3.0

Strings

Strings are defined either with a single quote or a double quotes. Many other languages interpret them differently.


In [57]:
mystring = 'hello'
print(mystring)
mystring = "hello"
print(mystring)


hello
hello

The difference between the two is that using double quotes makes it easy to include apostrophes (whereas these would terminate the string if using single quotes)


In [58]:
mystring = "Don't worry about apostrophes"
print(mystring)


Don't worry about apostrophes

As a side note, you can use "\" to "escape" special characters. Here's another way to deal with apostrophes:


In [60]:
mystring = 'You still don\'t have to worry about apostrophes'
print(mystring)


You still don't have to worry about apostrophes

Operators

Some the arithmetic operators can be applied to strings, though they have a different interpretation

  • + will concatenate two strings
  • * multiplies a string with an integer, i.e. the result is that many copies of the original string.
  • % has a very special purpose to fill in values into strings

Python provides a large number of operations to manipulate text strings. Examples are given at https://www.tutorialspoint.com/python/python_strings.htm

For the complete documentation refer to https://docs.python.org/2/library/string.html


In [14]:
# Practice adding some strings!

name = 'Joe'
hobby = 'skydiving'

print('Hi, my name is '+name+' and I like '+hobby+'!')


Hi, my name is Joe and I like skydiving!

In [64]:
# In-class exercise: 
# Append a line to finish this limmerick, then print it twice!

beginning = """There once was a man named Crocket
Who put his foot in a socket
When along came a witch,
Who turned on the switch,\n""" # "\n" insterts a newline
# source: Jeremy Diamond on http://home.earthlink.net/~kristenaa/nice/lims2f.html

end = "And rattled the change in his pocket.\n\n" # enter a line that rhymes with line 1 

#print (beginning+end)*2
print ("%s%s" % (beginning, end))*2
# your code goes here!


There once was a man named Crocket
Who put his foot in a socket
When along came a witch,
Who turned on the switch,
And rattled the change in his pocket.

There once was a man named Crocket
Who put his foot in a socket
When along came a witch,
Who turned on the switch,
And rattled the change in his pocket.


String Formatting

Python uses C-style string formatting to create new, formatted strings. The "%" operator is used to format a set of variables enclosed in a "tuple" (a fixed size list), together with a format string, which contains normal text together with "argument specifiers", special symbols like "%s" and "%d".

Some basic argument specifiers you should know: %s - String (or any object with a string representation, like numbers)

%d - Integers

%f - Floating point numbers

%.<number of digits>f - Floating point numbers with a fixed amount of digits to the right of the dot.

%x/%X - Integers in hex representation (lowercase/uppercase)


In [65]:
7./13.


Out[65]:
0.5384615384615384

In [66]:
print "The magic number is %.2f!" % (7.0/13.0)


The magic number is 0.54!

In [ ]:


In [69]:
# In-class exercise:
# Define output_str so that calling myadd(3, 5) displays a text "3 plus 5 is 8". 

def myadd(a,b):
    c = a+b
    output_str = "%f plus %f is %f" % (a,b,c) # yay, done!
    print(output_str)
    
myadd(3, 5)


3.000000 plus 5.000000 is 8.000000

Lists

Lists are construct for holding multiple objects or values of different types (if this makes sense). We can dynamically add, replace, or remove elements from a list.

Usually we iterate through list in order to perform some operations, though, we can also address a specific element by its position (index) in the list.

The + and * operators work on lists in a similar way as they do on strings.

Complete documentation at https://docs.python.org/2/tutorial/datastructures.html


In [70]:
mylist = [1, 2, "three", ("a", 7)]
print len(mylist)
print mylist


4
[1, 2, 'three', ('a', 7)]

In [71]:
mylist[3]


Out[71]:
('a', 7)

In [72]:
mylist[0]


Out[72]:
1

In [74]:
mylist[-2]


Out[74]:
'three'

In [75]:
mylist + [7]


Out[75]:
[1, 2, 'three', ('a', 7), 7]

In [76]:
mylist * 2


Out[76]:
[1, 2, 'three', ('a', 7), 1, 2, 'three', ('a', 7)]

List Comprehension

List comprehension can be thought of as a more "pythonic" way to loop over a list. It is a technique that comes in handy and is often used.


In [77]:
x = list(xrange(0,10))
print x


[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [80]:
# # One way to get y = 2^x:
x = xrange(0,10)
y1 = []
for element in x:
    y1.append(2**element) # note the indent here! whitespace matters!
print "y1 = "+str(y1)

# a more "pythonic way"
y2 = [2**element for element in x]
print "y2 = "+str(y2)


y1 = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
y2 = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]

In [23]:
[(i,j) for i in xrange(1,4) for j in xrange(1,4)]


Out[23]:
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]

In [24]:
[ [(i,j) for i in xrange(1,4) ] for j in xrange(1,4)]


Out[24]:
[[(1, 1), (2, 1), (3, 1)], [(1, 2), (2, 2), (3, 2)], [(1, 3), (2, 3), (3, 3)]]

In [ ]:


In [ ]:


In [ ]:


In [83]:
# in-class exercise:
# complete the code below to plot y = 3*sin(x/3):

import math as ma
import matplotlib.pyplot as plt
% matplotlib inline

x = xrange(-20,20)
y = [3.*ma.sin(xi/3.) for xi in x] # your code goes here!
plt.plot(x,y)

# plt.plot(*zip(*[(x,3.*ma.sin(x/3.)) for x in xrange(-20,20)]))


Out[83]:
[<matplotlib.lines.Line2D at 0x4b68410>]

Conditions

Python uses boolean variables to evaluate conditions. The boolean values True and False are returned when an expression is compared or evaluated.

Notice that variable assignment is done using a single equals operator "=", whereas comparison between two variables is done using the double equals operator "==". The "not equals" operator is marked as "!=".


In [85]:
x = 2
print(x == 2) # prints out True
print(x == 3) # prints out False
print(x <= 3) # prints out True
print(x >= 3) # prints out True


True
False
True
False

The "and", "or" and "not" boolean operators allow building complex boolean expressions, for example:


In [88]:
name = "John"
age = 23
if name == "John" and age == 23:
    print("Your name is John, and you are also 23 years old.")
else:
    print("You are not John.")
    
if name == "John" or name == "Rick":
    print("Your name is either John or Rick.")


Your name is John, and you are also 23 years old.
Your name is either John or Rick.

The "in" operator could be used to check if a specified object exists within an iterable object container, such as a list:


In [89]:
name = "John"
if name in ["John", "Rick"]:
    print("Your name is either John or Rick.")


Your name is either John or Rick.

Python uses indentation to define code blocks, instead of brackets. The standard Python indentation is 4 spaces, although tabs and any other space size will work, as long as it is consistent. Notice that code blocks do not need any termination.

Here is an example for using Python's "if" statement using code blocks:

if <statement is true>:
    <do something>
    ....
    ....
elif <another statement is true>: # else if
    <do something else>
    ....
    ....
else:
    <do another thing>
    ....
    ....

In [ ]:
x = 2
if x == 2:
    print("x equals two!")
else:
    print("x does not equal to two.")

A statement is evaulated as true if one of the following is correct:

1. The "True" boolean variable is given, or calculated using an expression, such as an arithmetic comparison. 
2. An object which is not considered "empty" is passed.

Here are some examples for objects which are considered as empty:

1. An empty string: "" 
2. An empty list: [] 
3. The number zero: 0 
4. The false boolean variable: False

In [103]:
# In-class exercise:
# Modify the following code to produce a function "is_even" that takes an argument x and prints
# "x is even" if it is even, and "x is not even" otherwise.
# If you call is_even(1), you should see "1 is not even"

def is_even(x):
    if x % 2==0:
        str2 = ""
    else:
        str2 = "not"
    outstr = "%d is %s even" % (x, str2)
    print outstr
    
def is_even2(x)
    print "%d is " % x +("" if x % 2 == 0 else "not ")+"even"
    

is_even(121)
is_even(4)


121 is not even
4 is  even

Loops

There are two types of loops in Python, for and while.

The "for" loop

For loops iterate over a given sequence. Here is an example: primes = [2, 3, 5, 7] for prime in primes: print(prime)

For loops can iterate over a sequence of numbers using the range and xrange functions. The difference between range and xrange is that the range function returns a new list with numbers of that specified range, whereas xrange returns an iterator, which is more efficient. (Python 3 uses the range function, which acts like xrange). Note that the range function is zero based.


In [104]:
for x in ['bob','mary','joe']:
    print x


bob
mary
joe

In [106]:
# Prints out the numbers 0,1,2,3,4
for x in range(5):
    print(x)

print('--------------')

# Prints out 3,4,5
for x in range(3, 6):
    print(x)

print('--------------')
    
# Prints out 3,5,7
for x in range(3, 8, 2):
    print(x)


0
1
2
3
4
--------------
3
4
5
--------------
3
5
7

"while" loops

While loops repeat as long as a certain boolean condition is met. For example:


In [108]:
count = 0
while count < 5:
    print(count)
    count += 1  # This is the same as count = count + 1
    
print 'done!'


0
1
2
3
4
done!

In [109]:
## compute the Greatest Common Denominator (GCD)
a = 15
b = 12

while a!=b:
    # put smaller number in a
    (a, b) = (a, b) if a<b else (b, a)
    b = b - a

print "The GCD is %d"%a


The GCD is 3

In [113]:
def fac(n):
    f = 1
    for m in range(1,n+1):
        f *= m 
    print "%d! is %d" % (n,f)
    
fac(5)


5! is 120

"break" and "continue" statements

break is used to exit a for loop or a while loop, whereas continue is used to skip the current block, and return to the "for" or "while" statement. A few examples:


In [116]:
# Prints out 0,1,2,3,4

# count = 0
# while True:
#     print(count)
#     count += 1
#     if count >= 5:
#         break

# Prints out only odd numbers - 1,3,5,7,9
for x in range(10):
    # Check if x is even
    if x % 2 == 0:
        continue
    print(x)


1
3
5
7
9

can we use "else" clause for loops?


In [117]:
# Prints out 0,1,2,3,4 and then it prints "count value reached 5"

count=0
while(count<5):
    print(count)
    count +=1
else:
    print("count value reached %d" %(count))

# Prints out 1,2,3,4
for i in range(1, 10):
    if(i%5==0):
        break
    print(i)
else:
    print("this is not printed because for loop is terminated because of break but not due to fail in condition")


0
1
2
3
4
count value reached 5
1
2
3
4

In [ ]:


In [ ]:

Functions and methods

Functions are a convenient way to divide your code into useful blocks, allowing us to order our code, make it more readable, reuse it and save some time. Also functions are a key way to define interfaces so programmers can share their code.

As we have seen on previous tutorials, Python makes use of blocks.

A block is a area of code of written in the format of: block_head: 1st block line 2nd block line

Where a block line is more Python code (even another block), and the block head is of the following format: block_keyword block_name(argument1,argument2, ...) Block keywords you already know are "if", "for", and "while".

Functions in python are defined using the block keyword "def", followed with the function's name as the block's name. For example:


In [136]:
def my_function():
    pass
    print("Hello From My Function!")

In [137]:
my_function()


Hello From My Function!

Functions may also receive arguments (variables passed from the caller to the function). For example:


In [138]:
def my_function_with_args(username, greeting):
    print("Hello, %s , From My Function!, I wish you %s"%(username, greeting))

In [139]:
my_function_with_args("Peter", "a wonderful day")


Hello, Peter , From My Function!, I wish you a wonderful day

Functions may return a value to the caller, using the keyword- 'return' . For example:


In [155]:
def sum_two_numbers(a, b=1):
    print "a = "+str(a)
    print "b = "+str(b)
    return a + b

In [156]:
x = sum_two_numbers(b=5,a=19)


a = 19
b = 5

In [157]:
x


Out[157]:
24

In [158]:
def my_fun(xi, yi):
    xi[4] = 0
    return yi*2

x = range(10)
y = 2
print x
print y

print "running my_fun"

my_fun(x,y)

print(x)
print(y)


[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2
running my_fun
[0, 1, 2, 3, 0, 5, 6, 7, 8, 9]
2

How to call functions


In [ ]:


In [ ]:
def my_function():
    print("Hello From My Function!")

def my_function_with_args(username, greeting):
    print("Hello, %s , From My Function!, I wish you %s"%(username, greeting))

def sum_two_numbers(a, b):
    return a + b

# print(a simple greeting)
my_function()

#prints - "Hello, John Doe, From My Function!, I wish you a great year!"
my_function_with_args("John Doe", "a great year!")

# after this line x will hold the value 3!
x = sum_two_numbers(1,2)

In [162]:
def my_fun2(x):
    return x, x**2, x**3

y1, y2, y3 = my_fun2(5)
print y1
print y2
print y3


5
25
125

In this exercise you'll use an existing function, and while adding your own to create a fully functional program.

  1. Add a function named list_benefits() that returns the following list of strings: "More organized code", "More readable code", "Easier code reuse", "Allowing programmers to share and connect code together"

  2. Add a function named build_sentence(info) which receives a single argument containing a string and returns a sentence starting with the given string and ending with the string " is a benefit of functions!"

  3. Run and see all the functions work together!


In [ ]:
# Modify this function to return a list of strings as defined above
def list_benefits():
    pass

# Modify this function to concatenate to each benefit - " is a benefit of functions!"
def build_sentence(benefit):
    pass

def name_the_benefits_of_functions():
    list_of_benefits = list_benefits()
    for benefit in list_of_benefits:
        print(build_sentence(benefit))

name_the_benefits_of_functions()

Methods

Methods are very similar to functions with the difference that, typically, a method associated with an objects.


In [163]:
s = "Hello WORLD"
s.lower()


Out[163]:
'hello world'

In [ ]:
3.75.as_integer_ratio()

Hint: while typing in the notebook or at the ipython prompt use the [TAB]-key after adding a "." (period) behind an object to see available methods:

  1. Type the name of an already defined object: s
  2. Add a period "." and hit the [TAB]-key: s. $\leftarrow$ This should show a list of available methods to a string.


In [ ]:


In [ ]:

Plotting something

  • Let's put some of our knowledge about lists and functions to use.
  • The following examples will create list of values, and then graph them.
  • We use a module of the Matplotlib library https://matplotlib.org/ The web-site provides detailed documentation and a wealth of examples.

In [ ]:
# These two lines are critical to using matplotlib within the noteboook
%matplotlib inline
import matplotlib.pyplot as plt

In [ ]:
x = range(10)
x

In [165]:
x = [float(i-50)/50.0 for i in range(100)]

In [ ]:
# from math import *

In [166]:
y = [ xx**2 for xx in x]
y2 = [xx**3 for xx in x]

In [168]:
plt.plot(x, y, label="x^2")
plt.plot(x, y2, label="x^3")
plt.legend(loc="best")
plt.title("Exponential Functions")
plt.show()



In [170]:
theta = [ ma.pi*0.02*float(t-50) for t in range (100)]
theta[:10]


Out[170]:
[-3.1415926535897936,
 -3.0787608005179976,
 -3.0159289474462017,
 -2.9530970943744057,
 -2.8902652413026098,
 -2.8274333882308142,
 -2.7646015351590183,
 -2.7017696820872223,
 -2.6389378290154264,
 -2.5761059759436304]

In [172]:
x = [ma.sin(t) for t in theta]
y = [ma.cos(t) for t in theta]

In [176]:
x,y = zip(*[(ma.sin(t), ma.cos(t)) for t in theta])

In [177]:
plt.figure(figsize=(6,6))
plt.plot(x,y)


Out[177]:
[<matplotlib.lines.Line2D at 0x5ad4910>]

Some Fun

Let's draw a picture of a bear in matplotlib. (Watch on YouTube https://www.youtube.com/watch?v=Jt1fSndR2bY)


In [ ]:
%