NOTE: the addutils
package is available at http://www.add-for.com/file/AddUtils-0.5.4-py34.zip
import addutils.toc ; addutils.toc.js(ipy_notebook=True)
Python is a modern, general-purpose, object-oriented, high-level programming language. It is a scripting language in the sense that python code runs (i.e. each expression is interpreted in turn) into the python interpreter, there is no linking, no compilation:
ruby, perl, php, matlab, R,
...C, C++, Java, Fortran
It is widely used in science and engineering, and has gain considerable traction in the domain of scientific computing over the past few years
Some positive attributes of Python that are often cited:
the philosophy of Python
import this
python scripts suffix .py
Shebang line:
#!/usr/bin/env/python
or path to your python binary
#!{HOME}/anaconda/bin/python
commented lines are marked by #
In the following IPython notebook cell I'm writing the content of the cell to a file
%%writefile print_upper.py
#!/Users/nicolasf/anaconda/anaconda/bin/python
# This is a python script
import sys # I import the sys module, part of the Python standard library
X = sys.argv[1:] # reading the command line arguments, X is list
X = " ".join(map(str,X)) # transform everything into a string
print(X.upper()) # printing the content, uppercase if applicable
!ls *.py
!chmod +x print_upper.py # we make the file executable
!./print_upper.py something another thing 1 2 3
!python print_upper.py something another thing 1 2 3
%run print_upper.py something another thing 1 2 3
a good idea is to use meaningful variable names in your scripts / notebooks
Can contain only letters, numbers and _ and must NOT begin by a number, also avoid Python reserved names
for = 1
Assignement operator is =
a = 5
a * 2
a += 2 # same as a = a + 2
a
a -=2
a
** is used for exponentiation
x = 2
x**2
pow(x,2)
NOTE: The case of integer division
In python 2.7 the ratio of two integers was always an integer, the results were truncated towards 0 if the result
was not an integer. This behavior changed from the first version of Python 3. To do integer division in Python 3, use the //
operator
9 / 5
9 // 5
x = 2.0 # can use 2. if you are lazy
type(x)
x = float(2)
type(x)
x
can be created using the J
notation or the complex
function
x = 2 + 3J
print(type(x)); print(x)
x = complex(2, 3)
print(type(x)); print(x)
x = 1
type(x)
x = int(1.2) ### will take the integer part
x
x = 1
type(x)
From Python 3, Long
integers and integers have been unified, see https://www.python.org/dev/peps/pep-0237/
x = 2**64
type(x)
x
Used to represent True
and False
. Usually they arise as the result of a logical operation
x = True
type(x)
x = 1
x == 0
y = (x == 0); y
x = [True, True, False, True]
sum(x)
You can define a string as any valid characters surrounded by single quotes
sentence = 'The Guide is definitive. Reality is frequently inaccurate.'; print(sentence)
Or double quotes
sentence = "I'd take the awe of understanding over the awe of ignorance any day."; print(sentence)
Or triple quotes
sentence = """Time is an illusion.
Lunchtime doubly so."""; print(sentence)
len(sentence) #!
And you can convert the types above (floats, complex, ints, Longs) to a string with the str
function
str(complex(2,3))
You can INDEX a string variable, indexing in Python starts at 0 (not 1): the subscript refers to an offset from the starting position of an iterable, so the first element has an offset of zero
If you want to know more follow why python uses 0-based indexing
sentence[0:4]
sentence[::-1]
But it is immutable: You cannot change string elements in place
sentence[2] = "b"
A lot of handy methods are available to manipulate strings
sentence.upper()
sentence.endswith('.')
sentence.split() # by default split on whitespaces, returns a list (see below)
"The answer is " + "42"
";".join(["The answer is ","42"]) # ["The answer is ","42"] is a list with two elements (separated by a ,)
a = 42
"The answer is %s" % ( a )
"The answer is %4.2f" % ( a )
"The answer is {0:<6.4f}, {0:<6.4f} and not {1:<6.4f} ".format(a,42.0001)
int_list = [1,2,3,4,5,6]
int_list
str_list = ['thing', 'stuff', 'truc']
str_list
lists can contain anything
mixed_list = [1, 1., 2+3J, 'sentence', """
long sentence
"""]
mixed_list
type(mixed_list[1])
lists
are iterable, their items (elements) can be accessed in a similar way as we saw for strings
int_list[0]
int_list[1]
int_list[::-1] ## same as int_list.reverse() but it is NOT operating in place
int_list.reverse()
int_list
lists can be nested (list of lists)
x = [[1,2,3],[4,5,6]]
x
from itertools import chain
list(chain(*x))
x[0]
x[1]
x[0][1]
append
is one of the most useful list methods
int_list.append(7); print(int_list)
lists are mutable: you can change their elements in place
int_list[0] = 2; print(int_list)
int_list.reverse()
int_list ### ! list object methods are applied 'in place'
int_list.count(2)
Tuples are also iterables, and they can be indexed and sliced like lists
int_tup = (1,2,3,5,6,7)
int_tup[1:3]
int_tup.index(2)
This construction is also possible
tup = 1,2,3
tup
Tuples ARE NOT mutable, contrary to lists
int_tup[0] = 1
Useful trick: zipping
lists
a = range(5); print(a)
b = range(5,10); print(b)
a + b
a = list(range(5))
b = list(range(5,10))
print(a)
print(b)
a + b
From Python 3 range
returns an iterator
, NOT a list, see https://docs.python.org/3.0/whatsnew/3.0.html#views-and-iterators-instead-of-lists
tuple(zip(a,b)) # returns a list of tuples
List comprehensions are one of the most useful and compacts Python expressions, I'm introducing that here but we'll see more about control flow structures later.
str_list
['my ' + x for x in str_list]
[x.upper() for x in str_list]
[x+y for x,y in zip(a,b)] # using zip (above)
a
[x + 6 if (x < 3) else x for x in a]
One of the more flexible built-in data structures is the dictionary. A dictionary maps a collection of values to a set of associated keys. These mappings are mutable, and unlike lists or tuples, are unordered. Hence, rather than using the sequence index to return elements of the collection, the corresponding key must be used. Dictionaries are specified by a comma-separated sequence of keys and values, which are separated in turn by colons. The dictionary is enclosed by curly braces. For example:
my_dict = {'a':16, 'b':(4,5), 'foo':'''(noun) a term used as a universal substitute
for something real, especially when discussing technological ideas and
problems'''}
my_dict
my_dict['foo']
'a' in my_dict # Checks to see if ‘a’ is in my_dict
my_dict.items() # Returns key/value pairs as list of tuples
my_dict.keys() # Returns list of keys
my_dict.values() # Returns list of values
my_dict['c']
If we would rather not get the error, we can use the get
method, which returns None
if the value is not present, or a value of your choice
my_dict.get('c')
my_dict.get('c', -1)
a = ['a','b','c']
b = [1,2,3]
type(tuple(a))
d = dict(zip(a,b))
d
Logical operators will test for some condition and return a boolean (True, False)
>
: Greater than>=
: Greater than or equal to<
: Less than<=
: Less than or equal to==
: Equal to!=
: Not equal tois / is not
Use == (!=) when comparing values and is (is not) when comparing identities.
x = 5.
type(x)
y = 5
type(y)
x == y
x is y # x is a float, y is a int, they point to different addresses in memory
a = 5
b = 6
a == b
a != b
(a > 4) and (b < 7)
(a > 4) and (b > 7)
(a > 4) or (b > 7)
All and Any can be used for a collection of booleans
x = [5,6,2,3,3]
cond = [item > 2 for item in x]
cond
all(cond)
any(cond)
In Python, there are no annoying curly braces (I'm looking at you R
), parenthesis, brackets etc as in other languages to delimitate flow control blocks, instead, the INDENTATION plays this role, which forces you to write clear(er) code ...
for x in range(10):
if x < 5:
print(x**2)
else:
print(x)
Note: The standard is to use 4 spaces (NOT tabs) for the indentation, set your favorite editor accordingly, for example in vi / vim:
set tabstop=4
set expandtab
set shiftwidth=4
set softtabstop=4
When editing a code cell in IPython, the indentation is handled intelligently, try typing in a new blank cell:
for x in xrange(10):
if x < 5:
print x**2
else:
print x
x = 10
if x < 10: # not met
x = x + 1
elif x > 10:
x = x - 1 # not met either
else:
x = x * 2
print(x)
x = 10
if (x > 5 and x < 8):
x = x+1
elif (x > 5 and x < 12):
x = x * 3
else:
x = x-1
print(x)
The basic structure of FOR loops is 
for item in iterable:
expression(s)
count = 0
# x = range(1,10) # range creates an iterator ...
x = range(1,10)
for i in x:
count += i
print(count)
You can see it as a generalization of the if ... else
construction, allowing more flexibility in handling failures in code
text = ('a','1','54.1','43.a')
for t in text:
try:
temp = float(t)
print(temp)
except ValueError:
#
print(str(t) + ' is Not convertible to a float')
A list of built-in exceptions is available here
As with Matlab and R, it's a good idea to write functions for bits of code that you use often.
The syntax for defining a function in Python is:
def name_of_function(arguments):
"Some code here that works on arguments and produces outputs"
...
return outputs
Note that the execution block must be indented ...
you can create a file (a module: extension .py required) which contains several functions, and can also define variables, and import some other functions from other modules
%%writefile some_module.py
PI = 3.14159 # defining a variable
from numpy import arccos # importing a function from another module
def f(x):
"""
This is a function which adds 5 to its argument
"""
return x + 5
def g(x, y):
"""
This is a function which sums its 2 arguments
"""
return x + y
import some_module
%whos
dir(some_module)
help(some_module)
some_module.PI
some_module.arccos?
some_module.f(7)
help(some_module.f)
from some_module import f
f(5)
import some_module as sm
sm.f(10)
The Zen of python says:
Namespaces are one honking great idea -- let's do more of those!
so don't do:
from some_module import *
As to avoid names conflicts ...
Functions can have positional as well as keyword arguments (with defaults, can be None
if that's allowed / tested)
positional arguments must always come before keyword arguments
def some_function(a,b, c=5,d=1e3):
res = (a + b) * c * d
return res
some_function(2,3)
some_function(2, 3, c=5, d=0.01)
you can return more than one output, by default will be a tuple
def some_function(a, b):
return a+1, b+1, a*b
x = some_function(2,3)
type(x)
a,b,c = some_function(2,3)