Introduction to Python

Monte Lunacek
Research Computing
CU Boulder

Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to humans what we want the computer to do.

Donald E. Knuth, Literate Programming, 1984

What is Python?

Python is a general-purpose programming language that blends procedural, functional, and object-oriented paradigms

Mark Lutz, Learning Python

Why Python?

Performance

CPU time is cheap, my time is expensive

Python environments

Interative coding

The Basics

Python Files

The import Statement

In [1]:
import math

Gives access to all functions and objects in the math module.

In [2]:
print math.pi
3.14159265359

In [3]:
print math.cos(10)
-0.839071529076

The prefix is helpful in avoiding name collision.

Alternative imports

Import all symbols so we no longer need the math prefix

In [6]:
from math import *

print pi
3.14159265359

Import select symbols

In [7]:
from math import pi, cos

myvar = 1.4
print cos(myvar)
0.1699671429

What is available?

In [8]:
print dir(math)
['__doc__', '__file__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']

In [9]:
help(math.pow)
Help on built-in function pow in module math:

pow(...)
    pow(x, y)
    
    Return x**y (x to the power of y).


Common imports:

In [10]:
import os, sys, math, shutil, re, subprocess

Comments

Every line of text in your file is considered python code uless it is preceeded by a # sign

In [11]:
# This is a comment
# It's ignored by the python interpreter

print(cos(pi)) # this is also ignored
-1.0

Variables

In [12]:
x87_ = 10
print x87_
10

Data types

In a dynamically typed language, the type is determined at assigment.

In [13]:
a = 2
b = 1e9
c = False
d = "A string"
In [14]:
print type(a)
print type(b)
print type(c)
print type(d)
<type 'int'>
<type 'float'>
<type 'bool'>
<type 'str'>

Type casting

In [15]:
print a,b,c,d
2 1000000000.0 False A string

In [16]:
print float(a)
print int(2.6)
print str(c)
2.0
2
False

In [17]:
print d, float(d)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-17-e54c9bdba762> in <module>()
----> 1 print d, float(d)

ValueError: could not convert string to float: A string
A string
In [18]:
print float("24")
 24.0

None

This is the null value type in Python.

In [19]:
value = None
print value
None

Example: Scientific Hello World

In [24]:
import math
r = float("4.2")
s = math.sin(r)
print "hello world! The sin(" +  str(r) + ") =", s
hello world! The sin(4.2) = -0.871575772414

Data Structures

Strings

In [19]:
s = "Hello world, world"
print type(s)
<type 'str'>

Length

In [20]:
print len(s)
18

In [21]:
s[0] = 'h'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-21-855719672658> in <module>()
----> 1 s[0] = 'h'

TypeError: 'str' object does not support item assignment

Find and replace (notice the immutability).

In [22]:
s2 = s.replace("world", "python")
s3 = s2.replace("Hello","monty")
print s
print s2
print s3
Hello world, world
Hello python, python
monty python, python

Slicing, more on this later

In [26]:
print s
print s[6:11]
Hello world, world
world

In [27]:
print s[6:]
world, world

In [28]:
print s[-2:]
ld

Concatenation

In [30]:
print s
print s3
Hello world, world
monty python, python

In [31]:
s4 = s + ' ' + s3
print s4
Hello world, world monty python, python

Find

In [7]:
print s4.find('world')
6

In [32]:
print s4.find('monty')
19

Formatting

In [33]:
print 'A string with value {0} and {1}'.format(10,20.3)
A string with value 10 and 20.3

More string help...

In [34]:
#help(str)

Lists

In [36]:
values = ['1',2,3.0,False]
print len(values)
print values
4
['1', 2, 3.0, False]

In [37]:
print type(values)
<type 'list'>

Slicing

In [38]:
print values
print values[1]
['1', 2, 3.0, False]
2

In [39]:
print values[:3]
['1', 2, 3.0]

In [40]:
print values[2:]
[3.0, False]

Append and remove

In [41]:
l = []
l.append(8)
l.append(10)
l.append(10)
l.append(12)
In [42]:
print l
[8, 10, 10, 12]

In [43]:
l.remove(10)
print l
[8, 10, 12]

In [44]:
l.remove(l[0]) # Can also say del
print l
[10, 12]

Generating lists

Create a list using the function range(start,stop,step).

In [52]:
l = range(0,10,2)
print l
[0, 2, 4, 6, 8]

In [53]:
l = range(-5,5)
print l
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]

In [54]:
line = "This is a    \t list -      \t of strings"
print len(line.split('\t'))
print line.split('\t')
3
['This is a    ', ' list -      ', ' of strings']

Sorting

Notice this is modifying the list.

In [70]:
l = range(-5,5)
print l

l.sort(reverse=True)
print l
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]
[4, 3, 2, 1, 0, -1, -2, -3, -4, -5]

Tuples

In [61]:
t = (10,40.0,"A")
In [12]:
print type(t), len(t)
<type 'tuple'> 3

In [13]:
t[1] = 'B'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-97fa05af13f0> in <module>()
----> 1 t[1] = 'B'

TypeError: 'tuple' object does not support item assignment

Unpacking

A Python favorite!

Unpack the tuple

In [14]:
print t
x,y,z = t #Unpacking
print z
(10, 40.0, 'A')
A

Unpack the list.

In [15]:
print l
A, B = l[:2]
print B
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]
-4

Dictionaries

Another Python favorite!
In [86]:
data = {}

data['k1'] = True
data['x2'] = 2
data[100] = 3.0
In [87]:
print data
{'x2': 2, 'k1': True, 100: 3.0}

In [88]:
print len(data), type(data)
3 <type 'dict'>

Add a new entry

In [89]:
data['k4'] = 100

Example

In [106]:
data = {'number': 10, 1:'string'}
data['c'] = [1,2,3,4]
In [93]:
print data
{1: 'string', 'c': [1, 2, 3, 4], 'number': 10}

In [94]:
print data[1]
string

In [95]:
print data['c'][3]
4

In [96]:
print data['number']
10

Default values

In [107]:
print data.get('number',0)
10

In [108]:
print data.get('B',0) # The key `B` does not exist
0

In [109]:
data['B'] = data.get('B',0) + 100
print data.get('B',0) 
100

Control Flow

Indention

There are no braces ({,}) around blocks of code in Python.

if( value < 0){
    std::cout << value << std::endl;
}
std::cout << "done" << std::endl;

if value < 0:
    print value
print done

if, elif, and else

In [2]:
cash = .9
if car < cash:
    print 'Enjoy your car ride'
elif bus < cash:
    print 'Another one rides the bus'
elif cash < 1.00:
    print 'stay home'
else:
    print 'Walking..'
stay home

If nothing else, walking.

The ternary expression

In [3]:
action = 'car' if car < cash else 'walking' #one-liner

print action
walking

The for loop

In [4]:
numbers = [1,2,3,4,5]
for i in numbers:
    print i
1
2
3
4
5

In [5]:
for i in range(10,20):
    print i,
10 11 12 13 14 15 16 17 18 19

In [6]:
names = ['pat','jonh']
for name in names:
    print name
pat
jonh

continue

You can skip part of the remaining block.

In [9]:
for i in xrange(10):
    print i,
    if i % 2 == 0:
        print 'even'
        continue
    print "---"
0 even
1 ---
2 even
3 ---
4 even
5 ---
6 even
7 ---
8 even
9 ---

break

Stop executing the entire loop.

In [10]:
for i in xrange(10):
    if i == 5:
        break
    print i
0
1
2
3
4

The while loop

In [21]:
count = 0
while (count < 10):
   print count,
   count += 1
0 1 2 3 4 5 6 7 8 9

When would you prefer a while loop to a for loop?

Exceptions

Gracefully handling errors.

In [12]:
num = '123.4d'
print float(num)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-12-320d5b550040> in <module>()
      1 num = '123.4d'
----> 2 print float(num)

ValueError: invalid literal for float(): 123.4d
In [13]:
try:
    print float(num)
except ValueError, e:
    print e
    print 'This is called Duck Typing'
invalid literal for float(): 123.4d
This is called Duck Typing

Multiple exceptions

In [21]:
def example(values):
    try:
        print float(values)
    except ValueError, e:
        print e
    except TypeError, e:
        print e
        
example(['3','4'])
example('A string?')
float() argument must be a string or a number
could not convert string to float: A string?

enumerate

Sometimes you want the index of a collection and the value. For example:

In [42]:
names = ['Deborah','Carla','Mary','Susan']
In [35]:
index = 0
for name in names:
    print index, names[index], name
    index += 1
0 Deborah Deborah
1 Carla Carla
2 Mary Mary
3 Susan Susan

In [36]:
for i, name in enumerate(names):
    print i, name
0 Deborah
1 Carla
2 Mary
3 Susan

sorted

In [15]:
print sorted(names)
['Carla', 'Deborah', 'Mary', 'Susan']

In [38]:
for name in sorted(names):
    print name,
Carla Deborah Mary Susan

reversed

In [39]:
for i in reversed(names):
    print i,
Susan Mary Carla Deborah

In [40]:
print list(reversed(names))
['Susan', 'Mary', 'Carla', 'Deborah']

In [41]:
print names
['Deborah', 'Carla', 'Mary', 'Susan']

zip

In [43]:
last = ['Smith','Mason','Carter','Dee']
print last
print names
['Smith', 'Mason', 'Carter', 'Dee']
['Deborah', 'Carla', 'Mary', 'Susan']

In [44]:
together = zip(names, last)
print together
[('Deborah', 'Smith'), ('Carla', 'Mason'), ('Mary', 'Carter'), ('Susan', 'Dee')]

In [45]:
for index, pair in  enumerate(zip(names,last)):
    print index, pair[0], pair[1]
0 Deborah Smith
1 Carla Mason
2 Mary Carter
3 Susan Dee

Comprehension

The Python consise expression.

In [47]:
names.append("Dan")
print names
['Deborah', 'Carla', 'Mary', 'Susan', 'Dan']

Create a list of just names that start with d

In [48]:
dnames = []
for name in names:
    if name.startswith('D'):
        dnames.append(name.lower())
print dnames
['deborah', 'dan']

List Comprehension: the "Python way"

In [49]:
dnames = None
dnames = [name.lower() for name in names if name.startswith('D')]
In [50]:
print dnames
['deborah', 'dan']

Dictonary items()

In [22]:
d = {'a': 10, 'b': 20, 'c': 30}
In [23]:
for i in d.keys():
    print i, d[i]
a 10
c 30
b 20

In [24]:
for k, v in d.items():
    print k, v
a 10
c 30
b 20

The Procedural Python

Outline:

Definition

In [4]:
def my_function():
    names = ['joe','nate']
    for k in names:
        print k
In [5]:
my_function()
joe
nate

Arguments

These are positional arguments

In [6]:
def my_function(a,b,c):
    print a,b,c

my_function(2,7,6)
2 7 6

In this example, the variables are named arguments.

In [9]:
def my_function(a,b,c=100):
    print a,b,c
    
my_function(c=2,b=4,a=50)
50 4 2

In [10]:
my_function(a=2,b=4)
2 4 100

Why not pass a dictionary as inputs? **kwargs

In [11]:
def print_keyword_args(**kwargs):
    for key, value in kwargs.iteritems():
        print key, value
In [12]:
print_keyword_args(a=20,b=30)
a 20
b 30

In [13]:
print_keyword_args(a=20,b=30,c=100)
a 20
c 100
b 30

*args

Passing an arbitrary number of arguments to your function

In [15]:
def print_args(*args):
    for index, value in enumerate(args):
        print index, value
In [16]:
print_args(10,20,40)
0 10
1 20
2 40

In [17]:
print_args(10,20)
0 10
1 20

Combination

In [19]:
def print_all(pos, *args, **kwargs):
    print "pos", pos
    
    for index, value in enumerate(args):
        print 'args', index, value
        
    for key, value in kwargs.iteritems():
        print 'kwargs', key, value
In [20]:
print_all("positional",10,20,30,a=40,b=50)
pos positional
args 0 10
args 1 20
args 2 30
kwargs a 40
kwargs b 50

Returning values

In [21]:
def my_function(a,b,c=100):
    if c  == 100:
        return a+b+c
    else:
        return a+b
In [22]:
value = my_function(10,10)
print value
120

In [23]:
value = my_function(1,1,10)
print value
2

Using a tuple

In [27]:
def my_function():
    a = 10
    b = 20.0
    c = "string"
    return a, b, c

Results as a tuple.

In [30]:
print my_function()
(10, 20.0, 'string')

Results as individual variables

In [31]:
x,y,z = my_function()
print x,y,z
10 20.0 string

Multiple values with a dictionary

In [32]:
def my_function():
    a = 10
    b = 20.0
    c = "string"
    return {'a': a, 'b': b, 'c': c}
In [33]:
values = my_function()
print values['a']
10