This section is meant as a general introduction to Python and is by far not complete. It is based amongst others on the IPython notebooks from J. R. Johansson, on http://www.stavros.io/tutorials/python/ and on http://www.swaroopch.com/notes/python.
Important: a very good interactive tutorial for Python can also be found on https://www.codecademy.com/learn/python
The goal of this section is to give you a short introduction to Python and help beginners to get familiar with this programming language.
Following chapters are available:
In [ ]:
import math
This includes the whole module and makes it available for use later in the program. For example, we can do:
In [ ]:
import math
x = math.cos(2 * math.pi)
print x
Importing the whole module us often times unnecessary and can lead to longer loading time or increase the memory consumption. Alternative to the previous method, we can also chose to import only a few selected functions from a module by explicitly listing which ones we want to import:
In [ ]:
from math import cos, pi
x = cos(2 * pi)
print x
It is also possible to give an imported module or symbol your own access name with the as
additional:
In [ ]:
import numpy as np
from math import pi as number_pi
x = np.rad2deg(number_pi)
print x
In [ ]:
help(math.log)
In [ ]:
math.log(10)
Out[ ]:
In [ ]:
math.log(10, 2)
Out[ ]:
Variable names in Python can contain alphanumerical characters a-z
, A-Z
, 0-9
and some special characters such as _
. Normal variable names must start with a letter.
By convention, variable names start with a lower-case letter, and Class names start with a capital letter.
In addition, there are a number of Python keywords that cannot be used as variable names. These keywords are:
and, as, assert, break, class, continue, def, del, elif, else, except, exec, finally, for, from, global, if, import, in, is, lambda, not, or, pass, print, raise, return, try, while, with, yield
In [ ]:
# variable assignments
x = 1.0
Although not explicitly specified, a variable does have a type associated with it. The type is derived form the value it was assigned.
In [ ]:
type(x)
Out[ ]:
If we assign a new value to a variable, its type can change.
In [ ]:
x = 1
In [ ]:
type(x)
Out[ ]:
If we try to use a variable that has not yet been defined we get an NameError
:
In [ ]:
print y
In [ ]:
# integers
x = 1
type(x)
Out[ ]:
In [ ]:
# float
x = 1.0
type(x)
Out[ ]:
In [ ]:
# boolean
b1 = True
b2 = False
type(b1)
Out[ ]:
In [ ]:
# string
s = "hallo world"
type(s)
Out[ ]:
In [ ]:
[1 + 2,
1 - 2,
1 * 2,
1 % 2]
Out[ ]:
In Python 2.7, what kind of division (/
) will be executed, depends on the type of the numbers involved. If all numbers are integers, the division will be an integer division, otherwise it will be a float division.
In [ ]:
# Integer devision, because both numbers are of type `int`
print 1 / 2
# Float devision, because at least one number is of type `float`
print 1 / 2.0
In [ ]:
# Note! The power operators in python isn't ^, but **
2 ** 2
Out[ ]:
and
, not
, or
.
In [ ]:
True and False
Out[ ]:
In [ ]:
not False
Out[ ]:
In [ ]:
True or False
Out[ ]:
>
, <
, >=
(greater or equal), <=
(less or equal), ==
equality, is
identical.
In [ ]:
2 > 1, 2 < 1
Out[ ]:
In [ ]:
2 > 2, 2 < 2
Out[ ]:
In [ ]:
2 >= 2, 2 <= 2
Out[ ]:
In [ ]:
# equal to
[1,2] == [1,2]
Out[ ]:
In [ ]:
# not equal to
print 2 != 3
In [ ]:
x = True
y = False
print not x
print x and y
print x or y
In [ ]:
"lo W" in "Hello World"
Out[ ]:
In [ ]:
"x" not in "Hello World"
Out[ ]:
In [ ]:
a = 2
a = a * 2
print a
The command a = a * 2
, can be shortcut to a *= 2
. This also works with +=
, -=
and /=
.
In [ ]:
b = 3
b *= 3
print b
In [ ]:
s = "Hello world"
type(s)
Out[ ]:
In [ ]:
# length of the string: number of characters in string
len(s)
Out[ ]:
In [ ]:
# replace a substring in a string with something else
s2 = s.replace("world", "test")
print s2
We can index a character in a string using []
:
In [ ]:
s[0]
Out[ ]:
Heads up MATLAB users: Indexing start at 0!
We can extract a part of a string using the syntax [start:stop]
, which extracts characters between index start
and stop
:
In [ ]:
s[0:5]
Out[ ]:
If we omit either (or both) of start
or stop
from [start:stop]
, the default is the beginning and the end of the string, respectively:
In [ ]:
s[:5]
Out[ ]:
In [ ]:
s[6:]
Out[ ]:
In [ ]:
s[:]
Out[ ]:
We can also define the step size using the syntax [start:end:step]
(the default value for step
is 1, as we saw above):
In [ ]:
s[::1]
Out[ ]:
In [ ]:
s[::2]
Out[ ]:
This technique is called slicing.
In [ ]:
print "str1" + "str2" + "str3" # strings added with + are concatenated without space
In [ ]:
print "str1" "str2" "str3" # The print statement concatenates strings differently
print "str1", "str2", "str3" # depending on how the inputs are specified
print ("str1", "str2", "str3") # See the three different outputs below
In [ ]:
print ("str1", 1.0, False) # The print statements converts all arguments to strings
In [ ]:
print "value = %f" %1.0 # we can use C-style string formatting
The string formatting specifier %.2f
transforms the input number into a string, that corresponds to a floating point number with 2 decimal places and the specifier %d
transforms the input number into a string, corresponding to a decimal number.
In [ ]:
s2 = "value1 = %.2f. value2 = %d" % (3.1415, 1.5)
print s2
In [ ]:
# alternative, more intuitive way of formatting a string can be achieved as follows
s3 = 'value1 = {0}, value2 = {1}'.format(3.1415, 1.5)
print s3
In [ ]:
print "Newlines are indicated by \nAnd tabs by \t."
print r"Newlines are indicated by \nAnd tabs by \t. Printed as rawstring"
In [ ]:
print "Name: %s\nNumber: %s\nString: %s" % ("Nipype", 3, 3 * "-")
In [ ]:
strString = """This is
a multiline
string."""
print strString
In [ ]:
print "This %(verb)s a %(noun)s." % {"noun": "test", "verb": "is"}
You can specify strings using single quotes such as 'Quote me on this'
.
All white space i.e. spaces and tabs, within the quotes, are preserved as-is.
Strings in double quotes work exactly the same way as strings in single quotes. An example is "What's your name?"
.
You can specify multi-line strings using triple quotes - ("""
or '''
). You can use single quotes and double quotes freely within the triple quotes. An example is:
In [ ]:
'''This is a multi-line string. This is the first line.
This is the second line.
"What's your name?," I asked.
He said "Bond, James Bond."
'''
Out[ ]:
In [ ]:
l = [1,2,3,4]
print type(l)
print l
We can use the same slicing techniques to manipulate lists as we could use on strings:
In [ ]:
print l
print l[1:3]
print l[::2]
Heads up MATLAB users: Indexing starts at 0!
In [ ]:
l[0]
Out[ ]:
Elements in a list do not all have to be of the same type:
In [ ]:
l = [1, 'a', 1.0]
print l
Python lists can be inhomogeneous and arbitrarily nested:
In [ ]:
nested_list = [1, [2, [3, [4, [5]]]]]
nested_list
Out[ ]:
Lists play a very important role in Python, and are for example used in loops and other flow control structures (discussed below). There are number of convenient functions for generating lists of various types, for example the range
function:
In [ ]:
start = 10
stop = 30
step = 2
range(start, stop, step)
Out[ ]:
In [ ]:
# convert a string to a list by type casting:
print s
s2 = list(s)
s2
Out[ ]:
In [ ]:
# sorting lists
s2.sort()
print s2
In [ ]:
# create a new empty list
l = []
# add an elements using `append`
l.append("A")
l.append("d")
l.append("d")
print l
We can modify lists by assigning new values to elements in the list. In technical jargon, lists are mutable.
In [ ]:
l[1] = "p"
l[2] = "t"
print l
In [ ]:
l[1:3] = ["s", "m"]
print l
Insert an element at an specific index using insert
In [ ]:
l.insert(0, "i")
l.insert(1, "n")
l.insert(2, "s")
l.insert(3, "e")
l.insert(4, "r")
l.insert(5, "t")
print l
Remove first element with specific value using 'remove'
In [ ]:
l.remove("A")
print l
Remove an element at a specific location using del
:
In [ ]:
del l[7]
del l[6]
print l
In [ ]:
point = (10, 20)
print type(point)
print point
If we try to assign a new value to an element in a tuple we get an error:
In [ ]:
point[0] = 20
In [ ]:
params = {"parameter1" : 1.0,
"parameter2" : 2.0,
"parameter3" : 3.0,}
print type(params)
print params
Dictionary entries can only be accessed by their key name.
In [ ]:
params["parameter2"]
Out[ ]:
In [ ]:
print "parameter1 = " + str(params["parameter1"])
print "parameter2 = " + str(params["parameter2"])
print "parameter3 = " + str(params["parameter3"])
In [ ]:
params["parameter1"] = "A"
params["parameter2"] = "B"
# add a new entry
params["parameter4"] = "D"
print "parameter1 = " + str(params["parameter1"])
print "parameter2 = " + str(params["parameter2"])
print "parameter3 = " + str(params["parameter3"])
print "parameter4 = " + str(params["parameter4"])
Whitespace is important in Python. Actually, whitespace at the beginning of the line is important. This is called indentation. Leading whitespace (spaces and tabs) at the beginning of the logical line is used to determine the indentation level of the logical line, which in turn is used to determine the grouping of statements.
This means that statements which go together must have the same indentation. Each such set of statements is called a block. We will see examples of how blocks are important later on.
One thing you should remember is that wrong indentation can give rise to errors. For example:
In [ ]:
i = 5
# Error below! Notice a single space at the start of the line
print 'Value is ', i
print 'I repeat, the value is ', i
In [ ]:
statement1 = False
statement2 = False
if statement1:
print "statement1 is True"
elif statement2:
print "statement2 is True"
else:
print "statement1 and statement2 are False"
For the first time, here we encountered a peculiar and unusual aspect of the Python programming language: Program blocks are defined by their indentation level. In Python, the extent of a code block is defined by the indentation level (usually a tab or say four white spaces). This means that we have to be careful to indent our code correctly, or else we will get syntax errors.
Examples:
In [ ]:
# Good indentation
statement1 = statement2 = True
if statement1:
if statement2:
print "both statement1 and statement2 are True"
In [ ]:
# Bad indentation!
if statement1:
if statement2:
print "both statement1 and statement2 are True" # this line is not properly indented
In [ ]:
statement1 = False
if statement1:
print "printed if statement1 is True"
print "still inside the if block"
In [ ]:
if statement1:
print "printed if statement1 is True"
print "now outside the if block"
In [ ]:
for x in [1,2,3]:
print x,
The for
loop iterates over the elements of the supplied list, and executes the containing block once for each element. Any kind of list can be used in the for
loop. For example:
In [ ]:
for x in range(4): # by default range start at 0
print x,
Note: range(4)
does not include 4 !
In [ ]:
for x in range(-3,3):
print x,
In [ ]:
for word in ["scientific", "computing", "with", "python"]:
print word,
To iterate over key-value pairs of a dictionary:
In [ ]:
for key, value in params.items():
print key + " = " + str(value)
Sometimes it is useful to have access to the indices of the values when iterating over a list. We can use the enumerate
function for this:
In [ ]:
for idx, x in enumerate(range(-3,3)):
print (idx, x)
In [ ]:
rangelist = range(10)
print rangelist
for number in rangelist:
# Check if number is one of
# the numbers in the tuple.
if number in [4, 5, 7, 9]:
# "Break" terminates a for without
# executing the "else" clause.
break
else:
# "Continue" starts the next iteration
# of the loop. It's rather useless here,
# as it's the last statement of the loop.
print number
continue
else:
# The "else" clause is optional and is
# executed only if the loop didn't "break".
pass # Do nothing
List comprehensions: Creating lists using for
loops:
A convenient and compact way to initialize lists:
In [ ]:
l1 = [x**2 for x in range(0,5)]
print l1
while
loops:
In [ ]:
i = 0
while i < 5:
print i
i = i + 1
print "done"
Note that the print "done"
statement is not part of the while
loop body because of the difference in indentation.
In [ ]:
def say_hello():
# block belonging to the function
print 'hello world'
say_hello() # call the function
Following an example where we also feed two arguments into the function.
In [ ]:
def print_max(a, b):
if a > b:
print a, 'is maximum'
elif a == b:
print a, 'is equal to', b
else:
print b, 'is maximum'
# directly pass literal values
print_max(3, 4)
x = 7
y = 7
# pass variables as arguments
print_max(x, y)
Very important: Variables inside a function are treated as local variables and therefore don't interfere with variables outside the scope of the function.
In [ ]:
x = 50
def func(x):
print 'x is', x
x = 2
print 'Changed local x to', x
func(x)
print 'x is still', x
The local scope of a variable inside a function can be extended with the keyword global
.
In [ ]:
x = 50
def func():
global x
print 'x is', x
x = 2
print 'Changed global x to', x
func()
print 'Value of x is', x
Optionally, but highly recommended, we can define a so called "docstring", which is a description of the functions purpose and behavior. The docstring should follow directly after the function definition, before the code in the function body.
In [ ]:
def func1(s):
"""
Print a string 's' and tell how many characters it has
"""
print s + " has " + str(len(s)) + " characters"
In [ ]:
help(func1)
In [ ]:
func1("test")
Functions that return a value use the return
keyword:
In [ ]:
def square(x):
"""
Return the square of x.
"""
return x ** 2
In [ ]:
square(4)
Out[ ]:
We can return multiple values from a function using tuples (see above):
In [ ]:
def powers(x):
"""
Return a few powers of x.
"""
return x ** 2, x ** 3, x ** 4
In [ ]:
powers(3)
Out[ ]:
And if we know that a function returns multiple outputs, we can store them directly in multiple variables.
In [ ]:
x2, x3, x4 = powers(3)
print x3
In [ ]:
def myfunc(x, p=2, debug=False):
if debug:
print "evaluating myfunc for x = " + str(x) + " using exponent p = " + str(p)
return x**p
If we don't provide a value of the debug
argument when calling the the function myfunc
it defaults to the value provided in the function definition:
In [ ]:
myfunc(5)
Out[ ]:
In [ ]:
myfunc(5, debug=True)
Out[ ]:
If we explicitly list the name of the arguments in the function calls, they do not need to come in the same order as in the function definition. This is called keyword arguments, and is often very useful in functions that takes a lot of optional arguments.
In [ ]:
myfunc(p=3, debug=True, x=7)
Out[ ]:
*args
and *kwargs
parametersSometimes you might want to define a function that can take any number of parameters, i.e. variable number of arguments, this can be achieved by using one (*args
) or two (**kwargs
) asterisks in the function declaration. *args
is used to pass a non-keyworded, variable-length argument list and the **kwargs
is used to pass a keyworded, variable-length argument list.
In [ ]:
def args_func(arg1, *args):
print "Formal arg:", arg1
for a in args:
print "additioanl arg:", a
args_func(1, "two", 3, [1, 2, 3])
In [ ]:
def kwargs_func(arg1, **kwargs):
print "kwargs is now a dictionary...\nType: %s\nContent: %s\n" % (type(kwargs), kwargs)
print "Formal arg:", arg1
for key in kwargs:
print "another keyword arg: %s: %s" % (key, kwargs[key])
kwargs_func(arg1=1, myarg2="two", myarg3=3)
In [ ]:
f1 = lambda x: x**2
# is equivalent to
def f2(x):
return x**2
In [ ]:
f1(2), f2(2)
Out[ ]:
This technique is useful for example when we want to pass a simple function as an argument to another function, like this:
In [ ]:
# map is a built-in python function
map(lambda x: x**2, range(-3,4))
Out[ ]:
Classes are the key features of object-oriented programming. A class is a structure for representing an object and the operations that can be performed on the object.
In Python a class can contain attributes (variables) and methods (functions).
A class is defined almost like a function, but using the class
keyword, and the class definition usually contains a number of class method definitions (a function in a class).
Each class method should have an argument self
as it first argument. This object is a self-reference.
Some class method names have special meaning, for example:
__init__
: The name of the method that is invoked when the object is first created.__str__
: A method that is invoked when a simple string representation of the class is needed, as for example when printed.
In [ ]:
class Point:
"""
Simple class for representing a point in a Cartesian coordinate system.
"""
def __init__(self, x, y):
"""
Create a new Point at x, y.
"""
self.x = x
self.y = y
def translate(self, dx, dy):
"""
Translate the point by dx and dy in the x and y direction.
"""
self.x += dx
self.y += dy
def __str__(self):
return("Point at [%f, %f]" % (self.x, self.y))
To create a new instance of a class:
In [ ]:
p1 = Point(0, 0) # this will invoke the __init__ method in the Point class
print p1 # this will invoke the __str__ method
To invoke a class method in the class instance p
:
In [ ]:
p2 = Point(1, 1)
print p2
p2.translate(0.25, 1.5)
print p2
You can access any value of a class object directly, for example:
In [ ]:
print p1.x
p1.x = 10
print p1
One of the most important concepts in good programming is to reuse code and avoid repetitions.
The idea is to write functions and classes with a well-defined purpose and scope, and reuse these instead of repeating similar code in different part of a program (modular programming). The result is usually that readability and maintainability of a program is greatly improved. What this means in practice is that our programs have fewer bugs, are easier to extend and debug/troubleshoot.
Python supports modular programming at different levels. Functions and classes are examples of tools for low-level modular programming. Python modules are a higher-level modular programming construct, where we can collect related variables, functions and classes in a module. A python module is defined in a python file (with file-ending .py
), and it can be made accessible to other Python modules and programs using the import
statement.
Consider the following example: the file mymodule.py
contains simple example implementations of a variable, function and a class:
In [ ]:
%%file mymodule.py
"""
Example of a python module. Contains a variable called my_variable,
a function called my_function, and a class called MyClass.
"""
my_variable = 0
def my_function():
"""
Example function
"""
return my_variable
class MyClass:
"""
Example class.
"""
def __init__(self):
self.variable = my_variable
def set_variable(self, new_value):
"""
Set self.variable to a new value
"""
self.variable = new_value
def get_variable(self):
return self.variable
Note: %%file
is called a cell-magic function and creates a file that has the following lines as content.
We can import the module mymodule
into our Python program using import
:
In [ ]:
import mymodule
Use help(module)
to get a summary of what the module provides:
In [ ]:
help(mymodule)
In [ ]:
mymodule.my_variable
Out[ ]:
In [ ]:
mymodule.my_function()
Out[ ]:
In [ ]:
my_class = mymodule.MyClass()
my_class.set_variable(10)
my_class.get_variable()
Out[ ]:
If we make changes to the code in mymodule.py
, we need to reload it using reload
:
In [ ]:
reload(mymodule)
Out[ ]:
To generate an exception we can use the raise
statement, which takes an argument that must be an instance of the class BaseExpection
or a class derived from it.
In [ ]:
raise Exception("description of the error")
A typical use of exceptions is to abort functions when some error condition occurs, for example:
def my_function(arguments):
if not verify(arguments):
raise Exception("Invalid arguments")
# rest of the code goes here
To gracefully catch errors that are generated by functions and class methods, or by the Python interpreter itself, use the try
and except
statements:
try:
# normal code goes here
except:
# code for error handling goes here
# this code is not executed unless the code
# above generated an error
For example:
In [ ]:
try:
print "test"
# generate an error: the variable test is not defined
print test
except:
print "Caught an exception"
To get information about the error, we can access the Exception
class instance that describes the exception by using for example:
except Exception as e:
In [ ]:
try:
print "test"
# generate an error: the variable test is not defined
print test
except Exception as e:
print "Caught an exception:" + str(e)
finally:
print "This block is executed after the try- and except-block."
In [ ]:
def some_function():
try:
# Division by zero raises an exception
10 / 0
except ZeroDivisionError:
print "Oops, invalid."
else:
# Exception didn't occur, we're good.
pass
finally:
# This is executed after the code block is run
# and all exceptions have been handled, even
# if a new exception is raised while handling.
print "We're done with that."
some_function()
In [ ]:
%%file demographics.csv
ds102,sub001,F,21.94
ds102,sub002,M,22.79
ds102,sub003,M,19.65
ds102,sub004,M,25.98
ds102,sub005,M,23.24
ds102,sub006,M,23.27
ds102,sub007,D,34.72
ds102,sub008,D,22.22
ds102,sub009,M,22.7
ds102,sub010,D,25.24
In [ ]:
%%file demographics.txt
ds102 sub001 F 21.94
ds102 sub002 M 22.79
ds102 sub003 M 19.65
ds102 sub004 M 25.98
ds102 sub005 M 23.24
ds102 sub006 M 23.27
ds102 sub007 D 34.72
ds102 sub008 D 22.22
ds102 sub009 M 22.7
ds102 sub010 D 25.24
In [ ]:
import csv
Before you can read or write any kind of file, you first have to open the file and go through it's content with a reader function or write the output line by line with a write function.
In [ ]:
f = open('demographics.csv','r') # open the file with reading rights = 'r'
data = [i for i in csv.reader(f) ] # go through file and read each line
f.close() # close the file again
for line in data:
print line
In [ ]:
data_new = [line[1:] for line in data]
for line in data_new:
print line
Now, we first have to open a file again, but this time with writing permissions = 'w'
. After it we can go through the file and write each line to the new csv-file.
In [ ]:
f = open('demographics_new.csv','w') # open a file with writing rights = 'w'
fw = csv.writer(f) # create csv writer
fw.writerows(data_new) # write content to file
f.close() # close file
Lets now check the content of demographics_new.csv
.
In [ ]:
!cat demographics_new.csv
In [ ]:
f = open('demographics.txt','r') # open file with reading rights = 'r'
# go through file and trim the new line '\n' at the end
datatxt = [i.splitlines() for i in f.readlines()]
# go through data and split elements in line by tabulators '\t'
datatxt = [i[0].split('\t') for i in datatxt]
f.close() # close file again
for line in datatxt:
print line
In [ ]:
f = open('demopgrahics_new.txt', 'w') # open file with writing rights = 'w'
datatxt_new = [line[1:] for line in datatxt] # delete first column of array
# Go through datatxt array and write each line with specific format to file
for line in datatxt_new:
f.write("%s\t%s\t%s\n"%(line[0],line[1],line[2]))
f.close() # close file
In [ ]:
with open('demographics.txt','r') as f:
datatxt = [i.splitlines() for i in f.readlines()]
datatxt = [i[0].split('\t') for i in datatxt]
for line in datatxt:
print line