a = 5 # Python is dynamically typed; this binds a to the int value 5 a + 6 # An expression -- in interactive mode the value of the expression is displayed a / 2 # Division of int rounds towards zero type(a) a = 5.0 # Rebind a to the float value 5.0 type(a) # Note the type has changed to float a / 2 # Float division (1+1j)/2 # Complex floats supported also 30**30 # Exponentiation -- note the native integer type 'int' promotes automatically to 'long' which is a big integer type import math math.cos(3.0) 5 > 3 # Type bool is a Boolean truth value not True True and False help(math) int(3.5) # Type cast to int type float(3) # Type cast to float type a = 'abc' + "def" # Single or double quotes construct str data type print a a[2:4] # Substring "slicing" notation, inclusive for start index, excludes end index, indexing starts at 0 a[:4] # Default start index is beginning a[2:] # Default end index is end of str help(str) # Useful string methods a.upper() L = [1, 2, 'a'] # Python list type is constructed with square brackets and can contain heterogeneous types L[0] # List indexing L[1:] # List slicing is the same as str slicing L[0] = 5 # Lists are mutable so their elements can be changed L[-1] # Negative slice indexes are relative to the end of the list, so L[-1] is the last element L len(L) help(list) # Help on list methods L + [5] # List arithmetic performs concatenation -- use Numpy arrays for fast matrix/vector operations range(5) # Builtin method range(n) constructs the list [0, 1, ..., n-1] range(3, 5) # As with slicing notation, range(a, b) returns [a, a+1, ..., b-1] sorted([3, 1, 2]) # Some builtin functions are useful for lists min([3, 1, 2]) t = (1, 2.0) # Tuples are created with parentheses and are immutable or const lists t[0] t[0] = 5 # One cannot modify an existing tuple (x, y) = (1, 0) # Tuples can be assigned to equal numbers of variables x y (x, y) = (y, x) # Swap two variables (x, y) d = {'a': 10, 'b': 20, 50: 100} # The dict type, a mapping. Keys and values can be heterogeneous types d['a'] d.keys() d[50] = 150 if True: # Indentation denotes block structure in Python so there are no 'end' keywords print 'Hello world' elif False and True: print 'Hardly likely' else: print 'Goodbye world' for i in [0, 1, 2]: # For loop -- builtin types list, tuple, dict support iteration (as do numpy arrays) print i for i in range(3): # Equivalent using range() print i i = 0 # Equivalent using while loop while i < 3: print i i += 1 # Note C++ operator i++ does not exist in Python i = 0 # Keywords 'continue' and 'break' work as in C++ (continue jumps to the next iteration of the loop, break exits the loop) while True: i += 1 if i == 1: continue elif i >= 4: break print i try: # Exception handling L = [1, 2] L[3] except IndexError: print 'Caught an exception' raise # Re-raise the exception def add(x, y=0): # Declare a function -- this takes the below function code and binds it to the symbol 'add' z = x + y return z add(1) add(1, 2) # Functions are dynamically typed so they work over various input types add(3.0, 4.5) add('Hello', ' world') another_add = add # Everything is an object in Python so we can copy this function to a different variable name another_add(3, 4) def add2(a): # Nested functions are allowed -- variables are looked up via lexical scopes (innermost scope to outermost) def add1(x): return x + 1 return add1(add1(a)) add2(1) counter = 0 def increment_counter(): global counter # Keyword global allows us to refer to the global scope inside a function counter += 1 return counter increment_counter() increment_counter() def read_counter(): # Keyword global is not necessary if the variable is on the right-hand side return counter read_counter() class LinkNode: # Linked list element type def __init__(self, value=None, next=None): # Constructor -- double underscores indicate special methods self.value = value self.next = next def __repr__(self): # String representation that is printed to the interactive prompt return 'LinkNode(' + str(self.value) + ', ' + repr(self.next) + ')' def to_list(node): # Convert to a list ans = [] while node is not None: # The value None is similar to C++'s type NULL. Compare with None using the 'a is b' operator. ans.append(node.value) node = node.next return ans a = LinkNode(1) a a = LinkNode(1, LinkNode(2)) a to_list(a) a.value a.next.value a.next.next is None f = open('test.txt', 'wt') # File object print >>f, 'Hello world!', 2, [3, 4] f.write('A fine dry day') f.close() !cat test.txt f = open('test.txt', 'rt') s = f.read() print s import os # Various os and path facilities are in os module os.path.join('dir', 'subdir', 'file') os.path.splitext('a.png') import sys # More system facilities in sys module sys.argv # Argument list (relevant if .py file was run from command line using python yourprogram.py) import numpy u = numpy.array([1.0, 2.5]) # Construct two vectors (1D arrays) v = numpy.array([2.0, 3.0]) u + v u * v # Multiplication is elementwise by default A = numpy.array([[1.0, 2.0], [3.0, 4.0]]) # Construct a matrix (2D array) numpy.dot(A, u) # Inner product (matrix multiply) numpy.dot(A, A) numpy.linalg.solve(A, u) # Invert the linear system (same as MATLAB's \) numpy.dot(numpy.linalg.inv(A), u) # Alternative way to invert. Note that numpy.linalg.pinv() (pseudoinverse) is more stable than inv() numpy.cos(u) # Math routines are available in numpy A[0] # Numpy arrays slice to give smaller numpy arrays or scalars A[0,0] = 5 # Array assignment A numpy.concatenate((A,A),0) # Concatenate along 1st dimension (dimension 0) numpy.vstack((A,A)) # Vertical concatenate numpy.hstack((A,A)) # Horizontal concatenate numpy.dstack((A,A)) # Stack along 'depth' dimension (3rd dimension) -- useful for images A = numpy.zeros((3,4),'uint8') # Most numpy constructors take an optional datatype which can be 'uint8', 'uint16', 'uint32', 'int8', 'float', 'double' A A+numpy.uint8(256) # Overflow wraps A = numpy.eye(3,3) A A[1:,1:3] # Slice a subarray import pylab import skimage import skimage.io import skimage.transform I = skimage.img_as_float(skimage.io.imread('/Users/connelly/Downloads/rgb.png')) I[5,3,0] # Image arrays are numpy arrays, indexed by y, x, channel I.shape # Dimensions: h, w, channels pylab.imshow(I) pylab.show() # The show() function may be necessary if the image is not displayed inline pylab.imshow(2*I) Ip = numpy.clip(2*I, 0, 1) # Change contrast. Use clip() to prevent under-flow or over-flow. clip(I, a, b) = minimum(maximum(I, a), b) pylab.imshow(Ip) pylab.imshow(numpy.fliplr(I)) # Flip horizontally pylab.imshow(I**2) # Gamma correct using exponentiation x = numpy.arange(10) # Numpy's arange() is an array variant of the builtin range() x y = numpy.random.random(10) # Uniform random values in interval [0, 1), of the given shape y pylab.plot(x, y) pylab.scatter(x, y) pylab.bar(x, y) Ip = skimage.transform.rotate(I, 45) # Rotate image pylab.imshow(Ip) T = skimage.transform.AffineTransform(scale=[0.5, 0.5]) # More general transformations Ip = skimage.transform.warp(I, T) pylab.imshow(Ip) def blur(I): # Naive blur ans = numpy.empty(I.shape) (h, w, channels) = I.shape for y in range(h): for x in range(w): y1 = max(y-1,0) x1 = max(x-1,0) y3 = min(y+1,h-1) x3 = min(x+1,w-1) for c in range(channels): ans[y,x,c] = (I[y1,x1,c]+I[y1,x,c]+I[y1,x3,c]+ I[y,x1,c]+I[y,x,c]+I[y,x3,c]+ I[y3,x1,c]+I[y3,x,c]+I[y3,x3,c])/9 return ans Ismall = skimage.transform.rescale(I, 1000.0/I.shape[0]) Ismall.shape %time Ip = blur(Ismall) I_stack = numpy.hstack((Ismall, Ip)) pylab.imshow(I_stack) skimage.io.imsave('birds.png', I_stack) !open birds.png import numba blur_jit = numba.autojit(blur) # Attempt to accelerate with JIT (autojit takes a function and returns a new JITed function). %time Ip = blur_jit(Ismall) # The JIT program is no faster. Culprit: min(), max() have not yet been accelerated by Numba. Solution: rewrite those functions in blur (or use Numba >= 0.9.1) def blur(I): ans = numpy.empty(I.shape) (h, w, channels) = I.shape for y in range(h): for x in range(w): y1 = y-1 if y1 < 0: y1 = 0 y3 = y+1 if y3 >= h: y3 = h-1 x1 = x-1 if x1 < 0: x1 = 0 x3 = x+1 if x3 >= w: x3 = w-1 for c in range(channels): ans[y,x,c] = (I[y1,x1,c]+I[y1,x,c]+I[y1,x3,c]+ I[y,x1,c]+I[y,x,c]+I[y,x3,c]+ I[y3,x1,c]+I[y3,x,c]+I[y3,x3,c])/9 return ans blur_jit = numba.autojit(blur) %time Ip = blur_jit(Ismall) # First run includes JIT compilation overhead %time Ip = blur_jit(Ismall) # Second run is fast pylab.rcParams['figure.figsize']=(8,7) # Change figure size