In [6]:
import numpy as np
import matplotlib.pyplot as plt
from numpy import array, cos, sin

In [1]:
%matplotlib inline


For loop and break¶

In [47]:
for i in range(20):
print(i)
if i > 30:
break
else:
print("maximum number of iteration reached")

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
not broken


Multiple assignments, comparisons¶

assigment: a=b=c=0, a,b = b,a, a=0 does not return anything

In [48]:
a = b = 3

In [49]:
print(a,b)

3 3

In [50]:
a = b = []

In [51]:
a is b

Out[51]:
True
In [52]:
a,b = 3,4

In [53]:
print(a,b)

3 4

In [54]:
a,b = b,a

In [55]:
print(a,b)

4 3

In [58]:
a,b,c,d = 1,2,3,"asf"

In [57]:
((a,b),c) = ((2,3),4)

In [60]:
(a = 2) == 3 # illegal!

Out[60]:
False
In [61]:
1/0

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-61-05c9758a9c21> in <module>()
----> 1 1/0

ZeroDivisionError: division by zero
In [62]:
$#   File "<ipython-input-62-921cc23c5c50>", line 1$#
^
SyntaxError: invalid syntax

In [63]:
1/0
$#   File "<ipython-input-63-1d81501595aa>", line 2$#
^
SyntaxError: invalid syntax

In [66]:
array(1)/array(0)

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/ipykernel/__main__.py:1: RuntimeWarning: divide by zero encountered in true_divide
if __name__ == '__main__':

Out[66]:
inf
In [65]:
1./0.

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-65-3543596c47ff> in <module>()
----> 1 1./0.

ZeroDivisionError: float division by zero
In [ ]:


In [ ]:



multiple comparison: 0 < x < 1

In [68]:
x = .5
print(0 < x < 1)
print( (0<x) < 1)

True
False

In [ ]:



Lists¶

deep copying [[2,3]], L*3?

in, not in for belonging to a list

In [71]:
L = [1,2,3,3,4]
5 in L
L.index(3)

Out[71]:
2
In [72]:
7 not in L

Out[72]:
True

list comprehension: with guard, multiple for inside

In [73]:
L

Out[73]:
[1, 2, 3, 3, 4]
In [76]:
[x**2 for x in L]

Out[76]:
[1, 4, 9, 9, 16]
In [82]:
[(i,j) for i in range(3) for j in range(2)]

Out[82]:
[[0, 0], [0, 1], [1, 0], [1, 1], [2, 0], [2, 1]]
In [81]:
array([i*j for i in range(3) for j in range(2)]).reshape((3,2))

Out[81]:
array([[0, 0],
[0, 1],
[0, 2]])
In [78]:
[x**2 for x in ["a", b] if type(x) == int]

Out[78]:
[4]

tuples

In [83]:
t = (2,3)

In [84]:
t[0]

Out[84]:
2
In [85]:
t[0] = 1

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-85-0a69537257d5> in <module>()
----> 1 t[0] = 1

TypeError: 'tuple' object does not support item assignment

strides, negative strides

slicing like a butcher: meaning of L[n:], L[-n:], etc. L[::-n], L[100:200] empty, replace chunks in a list

In [86]:
L

Out[86]:
[1, 2, 3, 3, 4]
In [87]:
L[100:200]

Out[87]:
[]
In [88]:
L[100]

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-88-78da2f882365> in <module>()
----> 1 L[100]

IndexError: list index out of range
In [89]:
a = array(L)
a[100:200]

Out[89]:
array([], dtype=int64)
In [ ]:



zip

In [90]:
L

Out[90]:
[1, 2, 3, 3, 4]
In [91]:
L1 = [10,20,30]

In [99]:
z = list(zip(L,L1))
print(z)

[(1, 10), (2, 20), (3, 30)]

In [102]:
L = [1, 2, 3, 3, 4]

In [97]:
L.append(L1)
print(L)

[1, 2, 3, 3, 4, [10, 20, 30]]

In [100]:
[x for x,y in z]

Out[100]:
[1, 2, 3]
In [104]:
el = list(enumerate(L))
print(el)

[(0, 1), (1, 2), (2, 3), (3, 3), (4, 4)]

In [105]:
[i for i,x in el if x == 3]

Out[105]:
[2, 3]
In [ ]:



Dictionaries¶

keys, items, values

In [106]:
d = {'a': 3, 'b': 4}

In [107]:
d['a']

Out[107]:
3
In [108]:
d['b']

Out[108]:
4
In [110]:
x = 'a'
d[x] = 100

In [ ]:


In [109]:
person1 = {'surname': 'Verdier', 'name': "Olivier"}


For else¶

Iterative algorithms

In [70]:
x = 1
max_iter = 100
for i in range(max_iter):
x = x**2
if x > 100:
break
else:
print("Algorithm did not converge in %s steps" % max_iter)

Algorithm did not converge in 100 steps


Plotting¶

plot labels and legends

In [71]:
xs = linspace(0,1,200)
plot(xs, cos(xs), label='cos')
plot(xs, sin(xs), label='sin')
legend()
savefig('sincos.pdf')


Function¶

Docstrings! (triple quotes)

In [72]:
def my_function():
"""
my_function is a super function
that's enough
"""
print("Hi! How are you?")

In [73]:
my_function?


Return multiple values

Functions always return None

Function arguments: named, default, star operations (varargs)

In [113]:
def power_function(a,b):
return a**b

In [114]:
power_function(2,3)

Out[114]:
8
In [115]:
param_list = [2,3]

In [116]:
power_function(*param_list)

Out[116]:
8
In [119]:
power_function(array([2,3]), array([3,4]))

Out[119]:
array([ 8, 81])
In [120]:
power_function(*[3,4])

Out[120]:
81
In [123]:
param_dict = { 'b': 3, 'c': 2}

In [124]:
power_function(**param_dict)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-124-4d23a083342e> in <module>()
----> 1 power_function(**param_dict)

TypeError: power_function() got an unexpected keyword argument 'c'
In [125]:
power_function??

In [126]:
power_function(b=3, a=2)

Out[126]:
8
In [127]:
b, a = 2, 3

In [ ]:
power_function(a=b, b=a)

In [128]:
def nice_function(a, b=3):
return a**b

In [129]:
nice_function(2)

Out[129]:
8
In [130]:
nice_function(2, b=5)

Out[130]:
32
In [131]:
nice_function(2,5)

Out[131]:
32
In [141]:
def super_function(a,b,*args, **kwargs):
print(args)
print(kwargs)

In [139]:
super_function(2,3,"hello",c=4,d=10)

('hello',)
{'c': 4, 'd': 10}

In [134]:
super_function(2,a=4,4,b=10)

  File "<ipython-input-134-e84df2085f0a>", line 1
super_function(2,a=4,4,b=10)
^
SyntaxError: non-keyword arg after keyword arg

In [144]:
def append_function(a, b=[]):
b.append(a)
return b

In [145]:
append_function(3,[4,5,6])

Out[145]:
[4, 5, 6, 3]
In [146]:
append_function(3)

Out[146]:
[3]
In [147]:
append_function(4)

Out[147]:
[3, 4]

closure example

In [91]:
def sin_freq(freq, x):
return sin(2*pi*freq*x)

In [92]:
def get_sin_with_freq(freq):
def sin_freq(x):
return sin(2*pi*freq*x)
return sin_freq

In [93]:
sin10 = get_sin_with_freq(10)

In [94]:
xs = linspace(0,1,200)
plot(xs, sin10(xs))

Out[94]:
[<matplotlib.lines.Line2D at 0x106a74048>]

Generators¶

Generators: enumerate, range, reversed

Exceptions¶

In [148]:
def divide(a,b):
if b == 0:
raise Exception("Oops, b is zero")
return a/b

In [149]:
divide(3,4)

Out[149]:
0.75
In [150]:
divide(3,0)

---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-150-24bf8d716600> in <module>()
----> 1 divide(3,0)

<ipython-input-148-11371656a320> in divide(a, b)
1 def divide(a,b):
2     if b == 0:
----> 3         raise Exception("Oops, b is zero")
4     return a/b

Exception: Oops, b is zero
In [ ]:



Namespaces, imports¶

Namespaces, import, %run, etc.

In [95]:
import example

In [96]:
example.J

Out[96]:
1j
In [97]:
example.imported_function(2.)

Out[97]:
200.0
In [98]:
%run example.py

In [99]:
imported_function(2.)

Out[99]:
200.0
In [156]:
from example import bisect as example_bisect

In [182]:
class Example:
pass
example = Example()

In [159]:
example.bisect = example_bisect

In [ ]:


In [101]:
from example import *

In [102]:
import example1
import example2
example1.imported_function
example2.imported_function

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-102-d85a77517064> in <module>()
----> 1 import example1
2 import example2
3 example1.imported_function
4 example2.imported_function

ImportError: No module named 'example1'
In [103]:
a = 0
a = 1

In [104]:
example = 10

In [105]:
import example as ex

In [106]:
ex.imported_function

Out[106]:
<function example.imported_function>

Arrays¶

array length is fixed: v[:2] = array([1]), or v.append

flags?

Boolean arrays: mask, example with rand(10,10) and capping at .5

In [160]:
M = np.random.randn(5,5)

In [161]:
print(M)

[[-0.45771511 -0.44600716 -0.0963087   0.36646952 -0.35648425]
[-0.532434    0.19209479  0.83525092 -0.24639756 -0.61241575]
[-0.82984776 -1.21664042  0.89142928  0.47979501 -0.30452319]
[ 0.48553935 -1.62094851  0.81100656  0.05521396 -0.74060706]
[ 1.54060755 -0.07426069 -0.40557241 -1.25481997 -1.77014925]]

In [163]:
mask = M > 0

[[False False False  True False]
[False  True  True False False]
[False False  True  True False]
[ True False  True  True False]
[ True False False False False]]

In [165]:
M[mask] = 100

In [166]:
M

Out[166]:
array([[ -4.57715111e-01,  -4.46007163e-01,  -9.63087029e-02,
1.00000000e+02,  -3.56484245e-01],
[ -5.32434001e-01,   1.00000000e+02,   1.00000000e+02,
-2.46397558e-01,  -6.12415752e-01],
[ -8.29847762e-01,  -1.21664042e+00,   1.00000000e+02,
1.00000000e+02,  -3.04523194e-01],
[  1.00000000e+02,  -1.62094851e+00,   1.00000000e+02,
1.00000000e+02,  -7.40607061e-01],
[  1.00000000e+02,  -7.42606888e-02,  -4.05572411e-01,
-1.25481997e+00,  -1.77014925e+00]])
In [167]:
M[M<0] = -100
print(M)

[[-100. -100. -100.  100. -100.]
[-100.  100.  100. -100. -100.]
[-100. -100.  100.  100. -100.]
[ 100. -100.  100.  100. -100.]
[ 100. -100. -100. -100. -100.]]


array comparison

In [168]:
M

Out[168]:
array([[-100., -100., -100.,  100., -100.],
[-100.,  100.,  100., -100., -100.],
[-100., -100.,  100.,  100., -100.],
[ 100., -100.,  100.,  100., -100.],
[ 100., -100., -100., -100., -100.]])
In [169]:
M == M

Out[169]:
array([[ True,  True,  True,  True,  True],
[ True,  True,  True,  True,  True],
[ True,  True,  True,  True,  True],
[ True,  True,  True,  True,  True],
[ True,  True,  True,  True,  True]], dtype=bool)
In [171]:
if (M == M).all():
print("M is equal to itself!")

M is equal to itself!


vectorize example with sign?

In [173]:
def sign(x):
if x < 0:
return -1
else:
return 1

In [174]:
data = np.arange(5)-2

In [175]:
data

Out[175]:
array([-2, -1,  0,  1,  2])
In [177]:
vsign = np.vectorize(sign)

In [178]:
vsign(data)

Out[178]:
array([-1, -1,  1,  1,  1])
In [176]:
sign(data)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-176-783031542db4> in <module>()
----> 1 sign(data)

<ipython-input-173-888533a22840> in sign(x)
1 def sign(x):
----> 2     if x < 0:
3         return -1
4     else:
5         return 1

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

reshape with -1

solve!!

In [110]:
M = array([[1.,2.], [3.,4.]])
V = array([2.,3.])

In [111]:
print(M, V)

[[ 1.  2.]
[ 3.  4.]] [ 2.  3.]

In [116]:
x = solve(M, V) # solves dot(M,x) == V

In [117]:
allclose(dot(M,x), V)

Out[117]:
True

No direct array comparision, use all, A < .75 & A > .25

Views?

In [123]:
print(M, V)

[[ 1.  2.]
[ 3.  4.]] [ 2.  3.]

In [124]:
M * V

Out[124]:
array([[  2.,   6.],
[  6.,  12.]])

Object oriented programming¶

Objects: example with Complex, __init__, __add__.

In [217]:
class Complex:
def __init__(self, x, y):
print("init!")
self.r = x
self.i = y

def abs(self):
return np.sqrt(self.r**2 + self.i**2)

return Complex(self.r + zz.r, self.i + zz.i)

def __str__(self):
return "%s + %s J" % (self.r, self.i)

def __repr__(self):
return "Complex({},{})".format(self.r, self.i)

In [218]:
z = Complex(1.,2.)

init!

In [219]:
z2 = Complex(10., 20.)

init!
init!

Out[219]:
Complex(11.0,22.0)
In [216]:
z + z2

init!

Out[216]:
11.0 + 22.0 J
In [202]:
z * z2

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-202-a1db40b12982> in <module>()
----> 1 z * z2

TypeError: unsupported operand type(s) for *: 'Complex' and 'Complex'
In [193]:
z.abs()

Out[193]:
2.2360679774997898
In [192]:
z.r,z.i

Out[192]:
(1.0, 2.0)
In [186]:
z.__dict__

Out[186]:
{'i': 2.0, 'r': 1.0}

Performance¶

In [223]:
def big_loop():
s = 0
for i in range(10000):
s = s + np.sqrt(i)

In [221]:
%prun big_loop()


In [224]:
%timeit big_loop()

100 loops, best of 3: 12.7 ms per loop

In [44]:
%prun?

In [227]:
import datetime

In [250]:
tic = datetime.datetime.now()
big_loop()
toc = datetime.datetime.now()
print(toc - tic)

0:00:00.013855


Numba¶

In [251]:
def get_grid(nh,nv):
x = np.linspace(-2,.8,nh)
y = np.linspace(-1.4,1.4,nv)
return np.meshgrid(x,y,indexing='ij')

In [253]:
def mandel_py(w,h,maxit=20):
# prepare initial points
x, y = get_grid(w,h)
c = x+y*1j
# where to store output
output = np.zeros(c.shape, dtype=int) + maxit
for i in range(h): # loop 1
for j in range(w): # loop 2
z = 0.
c0 = c[i,j]
for k in range(maxit): # loop 3!!
z = z**2 + c0
if z*z.conjugate() > 4.0:
output[i, j] = k
break
return output.T

In [264]:
nb.jit(nopython=True)(mandel_py)(200,200)

---------------------------------------------------------------------------
TypingError                               Traceback (most recent call last)
<ipython-input-264-f046d1b4de87> in <module>()
----> 1 nb.jit(nopython=True)(mandel_py)(200,200)

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/dispatcher.py in _compile_for_args(self, *args, **kws)
169         assert not kws
170         sig = tuple([self.typeof_pyval(a) for a in args])
--> 171         return self.compile(sig)
172
173     def inspect_llvm(self, signature=None):

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/dispatcher.py in compile(self, sig)
346                                           self.py_func,
347                                           args=args, return_type=return_type,
--> 348                                           flags=flags, locals=self.locals)
349
350             # Check typing error if object mode is used

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/compiler.py in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library)
635     pipeline = Pipeline(typingctx, targetctx, library,
636                         args, return_type, flags, locals)
--> 637     return pipeline.compile_extra(func)
638
639

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/compiler.py in compile_extra(self, func)
356                 raise e
357
--> 358         return self.compile_bytecode(bc, func_attr=self.func_attr)
359
360     def compile_bytecode(self, bc, lifted=(), lifted_from=None,

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/compiler.py in compile_bytecode(self, bc, lifted, lifted_from, func_attr)
365         self.lifted_from = lifted_from
366         self.func_attr = func_attr
--> 367         return self._compile_bytecode()
368
369     def compile_internal(self, bc, func_attr=DEFAULT_FUNCTION_ATTRIBUTES):

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/compiler.py in _compile_bytecode(self)
622
623         pm.finalize()
--> 624         return pm.run(self.status)
625
626

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/compiler.py in run(self, status)
248                     # No more fallback pipelines?
249                     if is_final_pipeline:
--> 250                         raise patched_exception
251                     # Go to next fallback pipeline
252                     else:

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/compiler.py in run(self, status)
240             for stage, stage_name in self.pipeline_stages[pipeline_name]:
241                 try:
--> 242                     res = stage()
243                 except _EarlyPipelineCompletion as e:
244                     return e.result

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/compiler.py in stage_nopython_frontend(self)
453                 self.args,
454                 self.return_type,
--> 455                 self.locals)
456
457         with self.fallback_context('Function "%s" has invalid return type'

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/compiler.py in type_inference_stage(typingctx, interp, args, return_type, locals)
749         infer.seed_type(k, v)
750
--> 751     infer.build_constraint()
752     infer.propagate()
753     typemap, restype, calltypes = infer.unify()

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/typeinfer.py in build_constraint(self)
492         for blk in utils.itervalues(self.blocks):
493             for inst in blk.body:
--> 494                 self.constrain_statement(inst)
495
496     def propagate(self):

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/typeinfer.py in constrain_statement(self, inst)
649     def constrain_statement(self, inst):
650         if isinstance(inst, ir.Assign):
--> 651             self.typeof_assign(inst)
652         elif isinstance(inst, ir.SetItem):
653             self.typeof_setitem(inst)

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/typeinfer.py in typeof_assign(self, inst)
689                                               src=value.name, loc=inst.loc))
690         elif isinstance(value, (ir.Global, ir.FreeVar)):
--> 691             self.typeof_global(inst, inst.target, value)
692         elif isinstance(value, ir.Arg):
693             self.typeof_arg(inst, inst.target, value)

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/numba/typeinfer.py in typeof_global(self, inst, target, gvar)
754         else:
755             raise TypingError("Untyped global name '%s'" % gvar.name,
--> 756                               loc=inst.loc)
757
758     def typeof_expr(self, inst, target, expr):

TypingError: Failed at nopython (nopython frontend)
Untyped global name 'get_grid'
File "<ipython-input-253-ff821fe7c6f4>", line 3
In [265]:
def mandel_np(w,h,maxit=20):
# prepare initial points
x, y = get_grid(w,h)
c = x+y*1j
# where to store output
output = np.zeros_like(c, dtype=int) + maxit
z = np.zeros_like(c)
for k in range(maxit):
z = z**2 + c
return output.T

In [266]:
plt.imshow(mandel_py(200,200))

Out[266]:
<matplotlib.image.AxesImage at 0x109c2bd30>
In [262]:
%timeit mandel_np(200,200)

100 loops, best of 3: 9.83 ms per loop

/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/ipykernel/__main__.py:10: RuntimeWarning: overflow encountered in multiply
/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/ipykernel/__main__.py:10: RuntimeWarning: invalid value encountered in multiply
/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/ipykernel/__main__.py:9: RuntimeWarning: overflow encountered in square
/Users/olivier/anaconda/envs/python3/lib/python3.4/site-packages/ipykernel/__main__.py:9: RuntimeWarning: invalid value encountered in square

In [147]:
zeros_like?

In [150]:
%timeit mandel_py(200,200)

1 loops, best of 3: 703 ms per loop

In [256]:
import numba as nb

In [257]:
def mandel_raw(grid, output,maxit):
for i in range(grid.shape[0]): # loop 1
for j in range(grid.shape[1]): # loop 2
z = 0.+0j
c0 = grid[i,j]
for k in range(maxit): # loop 3!!
z = z**2 + c0
if z.real*z.real + z.imag*z.imag > 4.0:
output[i, j] = k
break
mandel_nb = nb.jit('void(c16[:,:],i8[:,:],i8)', nopython=True)(mandel_raw)

def mandel_opt(w,h,maxit=20):
x, y = get_grid(w,h)
grid = x+y*1j
output = np.zeros_like(grid, dtype=int) + maxit
mandel_nb(grid,output,maxit)
return output.T


In [260]:
%timeit mandel_opt(200,200)

100 loops, best of 3: 2.13 ms per loop

In [259]:
plt.imshow(mandel_opt(200,200))

Out[259]:
<matplotlib.image.AxesImage at 0x1099f1208>
In [ ]:


In [155]:
imshow(mandel_py(200,200))

Out[155]:
<matplotlib.image.AxesImage at 0x109df5160>
In [156]:
%prun mandel_py(200,200)



Testing?¶

In [ ]: