Python notes

From OriWiki

Jump to: navigation, search

Python clips

Contents

yield generators and iterators

def f():
    i = 0 
    while i<10:
        yield i 
        i += 1
    raise StopIteration
 
for x in f():
    print x 
 
it = f()
while True:
    try:
        print it.next()
    except:
        print "done"
        break




how to find the version

python version

import sys
print sys.version 

package version

import sympy
print sympy.version

site packages path in ubuntu

 /usr/lib/python2.5/site-packages

or sometime (when I installed it through a self extracted file):

/var/lib/python-support/python2.5/

Web programming

web programming entry point

Client side programming

Grab a document from the web

import urllib 
 
doc = urllib.urlopen('http://www.orimosenzon.com').read()
print doc

Server side programming

forward function declaration

when is it needed? It seems like the function need to be encounter by the parser before it is being called but not necessarily before code-wise

# foo2() # NameError: name 'foo2' is not defined 
def foo1():
    print "foo1()"
    foo2() # fine! 
 
def foo2():
    print "foo2()"
foo1()

help

help(.capitalize)

find out all the methods of a type

>>> dir('ori')

lists

[1] is a list empty?

if not aList:
   ...

list indexing

sublist:

>>> a = [11,22,33,44,55,66,77]
>>> a[2:5]
[33, 44, 55]
>>> a[1:7:2]  # [from, )too, step
[22, 44, 66]

clonning

shallow copy:

>>> a = [11,22,33]
>>> b = a 
>>> b.remove(22)
>>> b
[11, 33]
>>> a
[11, 33]

real clonning

>>> a = [11,22,33]
>>> b = a[0:len(a)]
>>> b.remove(22)
>>> b
[11, 33]
>>> a
[11, 22, 33]

deleting an element from a list

the parameter to remove is the value to be removed:

>>> a = [11,22,33]
>>> a.remove(22)
>>> a
[11, 33]

combine with C

[2]

function documentation

"global documentation"
 
def foo():
    "foo documentation"
 
def foo1():
    """This is the documentation of foo1() ..
Using a mutiline string  
"""
 
print __doc__ 
 
print foo.__doc__
 
print foo1.__doc__

global and local scopes

Local variable shade the global one while in function:

 
a = 'out' 

def foo():
    a = 'in' 
    print a

foo()
print a

#in 
#out 

global makes the local variable a refernce to the global variable:

a = 'out' 

def foo():
    global a 
    a = 'in' 
    print a

foo()
print a

#in 
#in 

Unlike c, a scope is not a local variable environment:

a = 'out' 

if True:
    a = 'in' 
    print a

print a

# in 
# in 

exception handling

try:
    #'dd'+4
    a = 7/0
    print a
except ZeroDivisionError:
    print "wow.. devision by zero occured.."
except:
    print "something happened" 
    raise 

breaking code lines

print \
      "hi,    how's stuff?"
print "hi,   \
how's stuff?"

(note that in this case it seems very important to have EOL immediately after the \ )

multiline string

print """ hi,
I hope you cope,
take care
"""

stdout and stderr

import sys
sys.stdout.write('this goes to stdout')  
sys.stderr.write('this goes to stderr')  
./check.py > tmp.out 
./check.py 2> tmp.out 
./check.py &> tmp.out

cygwin python

Note that if the %path% variable contain the cygwin/bin before the python, the python is run in a special cygwin mode the effects pathes (for example sys.prefix)

two command in same line

Just separate them with a ;

print "hi"; print "bye"

Command line execution

python -c "..." 

For example

python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-0.97'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-0.97'), join(sys.prefix, 'scons')] + sys.path; print sys.path"

type

>>> c = (1,2)
>>> type(c)
<type 'tuple'>
>>> type(a)
<type 'numpy.ndarray'>
>>> type(b)
<type 'list'>
>>> c = ([1],[2])
>>> type(c)
<type 'tuple'>
>>> c[1]
[2]
>>> type(c[0])
<type 'list'>

NumPy

from numpy import *
 
>>> vector1 = array((1,2,3,4,5))

>>> print vector1

[1 2 3 4 5]

>>> matrix1 = array(([0,1],[1,3]))

>>> print matrix1

[[0 1]

[1 3]]

>>> print vector1.shape, matrix1.shape

(5,) (2,2)

>>> print vector1 + vector1

[ 2 4 6 8 10]]

>>> print matrix1 * matrix1

[[0 1] # note that this is not the matrix

[1 9]] # multiplication of linear algebra

matrix multiplication

>>> c1 = matrix(([0,1],[1,0]))
>>> c1
matrix([[0, 1],
        [1, 0]])
>>> c1 * c1
matrix([[1, 0],
        [0, 1]])
>>>
>>> matrix("1 2;3 4")
matrix([[1, 2],
        [3, 4]])


>>> zeros((2,2))
array([[ 0.,  0.],
       [ 0.,  0.]])
>>> ones((2,2))
array([[ 1.,  1.],
       [ 1.,  1.]])
>>> help(numpy) 

>>> identity(3)
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
>>> m = identity(2)
>>> m[0,0], m[0,1], m[1,0], m[1,1]
(1.0, 0.0, 0.0, 1.0)


Numpy contains both an array class and a matrix class. The array class is intended to be a general-purpose n-dimensional array for many kinds of numerical computing, while matrix is intended to facilitate linear algebra computations specifically. In practice there are only a handful of key differences between the two.

Operator *, dot(), and multiply()

For array, '*' means element-wise multiplication, and the dot() function is used for matrix multiplication.

For matrix, '*' means matrix multiplication, and the multiply() function is used for element-wise multiplication.

Handling of vectors (rank-1 arrays)

For array, the vector shapes 1xN, Nx1, and N are all different things. Operations like A[:,1] return a rank-1 array of shape N, not a rank-2 of shape Nx1. Transpose on a rank-1 array does nothing.

  • For matrix, rank-1 arrays are always upconverted to 1xN or Nx1 matrices (row or column vectors). A[:,1] returns a rank-2 matrix of shape Nx1.
  • Handling of higher-rank arrays (rank > 2)

array objects can have rank > 2. matrix objects always have exactly rank 2.

Convenience attributes

array has a .T attribute, which returns the transpose of the data. matrix also has .H, .I, and .A attributes, which return the conjugate transpose, inverse, and asarray() of the matrix, respectively.

Convenience constructor

  • The array constructor takes (nested) Python sequences as initializers. As in, array([[1,2,3],[4,5,6]]).
  • The matrix constructor additionally takes a convenient string initializer. As in matrix("[1 2 3; 4 5 6]").

There are pros and cons to using both:

array Pros and Cons

  •  :) You can treat rank-1 arrays as either row or column vectors. dot(A,v) treats v as a column vector, while dot(v,A) treats v as a row vector. This can save you having to type a lot of transposes.
  • <:( Having to use the dot() function for matrix-multiply is messy -- dot(dot(A,B),C) vs. A*B*C.
  •  :) Element-wise multiplication is easy: A*B.
  •  :) array is the "default" NumPy type, so it gets the most testing, and is the type most likely to be returned by 3rd party code that uses NumPy.
  •  :) Is quite at home handling data of any rank.
  •  :) Closer in semantics to tensor algebra, if you are familiar with that.
  •  :) All operations (*, /, +, ** etc.) are elementwise

matrix Pros and Cons

  •  :\ Behavior is more like that of MATLABĀ® matrices.
  • <:( Maximum of rank-2. To hold rank-3 data you need array or perhaps a Python list of matrix.
  • <:( Minimum of rank-2. You cannot have vectors. They must be cast as single-column or single-row matrices.
  • <:( Since array is the default in NumPy, some functions may return an array even if you give them a matrix as an argument. This shouldn't happen with NumPy functions (if it does it's a bug), but 3rd party code based on NumPy may not honor type preservation like NumPy does.
  •  :) A*B is matrix multiplication, so more convenient for linear algebra.
  • <:( Element-wise multiplication requires calling a function, multipy(A,B).
  • <:( The use of operator overloading is a bit illogical: * does not work elementwise but / does.

Summary

There are solid arguments for both camps. It probably boils down mostly to how much actual matrix multiplication you do in your code, and how much you appreciate the error checking benefits of having a row vs column vector distinction. In the end, you don't really have to choose one or the other. You can mix-and-match. You can use array for the bulk of your code, and switch over to matrix in the sections where you have nitty-gritty linear algebra.

power: **

invert: m ** -1

polynomials

A one-dimensional polynomial class.

p = poly1d([1,2,3]) constructs the polynomial x**2 + 2 x + 3

p(0.5) evaluates the polynomial at the location

p.r is a list of roots

p.c is the coefficient array [1,2,3]

p.order is the polynomial order (after leading zeros in p.c are removed)

p[k] is the coefficient on the kth power of x (backwards from

    sequencing the coefficient array.

polynomials can be added, substracted, multplied and divided (returns

    quotient and remainder).

asarray(p) will also give the coefficient array, so polynomials can

    be used in all functions that accept arrays.

p = poly1d([1,2,3], variable='lambda') will use lambda in the

string representation of p.

else in loop

i=0
while i<7:
  if i>5: #try 8
    break
  i += 1
else:
  print "end due to completion"

string

find index of first ocurance

s.find("*",1)

classes

basic


class A:
    _a = 0
    def foo(self):
        print "A.foo() invoked"
        self._a += 1
       
a = A()
b = A()
a.foo()
A.foo(a)

b._a = 17
print a._a,b._a

member variable creation on demand

class A:
    def createData(self):
        self.data = 17  # this command actually created this member variable 
    def printData(self):
        print self.data

a = A()
a.createData()
a.printData()

polymorphism

class A:
    "This is the documentation of A.."
    def foo(self):
        print "A.foo() invoked"

class B:
    "this is b.."
    def foo(self):
        print "B.foo() invoked"
   

def f(obj):
    obj.foo()

map(f,[A(),B()])   

class iterator

class A:
    "This is the documentation of A.."
    data = [1,2,3,4]
    def __iter__(self):
        return AIter(self)
   
class AIter:
    def __init__(self,obj):
        self.obj = obj
        self.i = 0
    def next(self):
        if self.i == len(self.obj.data):
            raise StopIteration
        else:
            ret = self.obj.data[self.i]
            self.i += 1
            return ret
       
# now..
for i in A():
    print i

functional programming


def compose(f1,f2):
    return lambda x:f1(f2(x))
print compose(lambda x:x+1,lambda x:2*x)(3)
--
def mymap(f1,lst):
    for x in lst:
        f1(x)

def f(x):
    print x+1
mymap(f,[1,2,3])

---
print map(lambda x:x+1,[1,2,3])

import

* import M
let you do M.foo()

from M import foo
let you do foo()

from M import *
 like using namespace...

Dictionary

python build in type to represent map (hash-table functionality)

myDict = {'ori':17, 'yosi':21, 'motke':107}
myDict['ori'] = 18 
print myDict['yosi']
myDict.keys()
myDict.values()
myDict.get('yosi')
myDict.get('yosi',-1) # gives 21
myDict.get('yosii',-1) # gives -1 (which is the default value) 

default values for parameters

def f(a='a',b='b',c='c'):
    print a+' '+b+' '+c

f()       # a b c
f(b='b1') # a b1 c

formated string

a = 'really, %s is nice' % 'yosi'


'hello %s, how are %s?' % ('there','you')

(Is this the closet we get in Python to Perl's string interpulation?)

file handling

f=open('file.txt', 'r')
content = f.read()
print content


import os

# os.chdir('/home')
files = os.listdir('/home')
for file in files:
    print file

# os.system('ls')

glob

import glob

files = glob.glob('*.txt')
for f in files: 
    print f

file traversal

import os

def traverse(path):
    files = os.listdir(path)
    for f in files:
        pathf = path+'/'+f
        if os.path.isdir(pathf):
            print '>>>>>'+f
            traverse(pathf)
            print '<<<<<'+f 
        else:
            print f

traverse('.')

__cmp__ and __str__

class A:
    # m_data
    def __init__(self,data):
        self.m_data = data
    def __str__(self):
        return '[A: '+str(self.m_data)+']'
    def _cmp__(self,other):
        return cmp(self.m_data,other.m_data)
        

a1 = A(17)
a2 = A(18)
print a1
print cmp(a1,a2)

input from console

print 'please enter a number'
a = raw_input()
print 'you entered '+a  

random

import random 
print random.randint(1,100)
import random 
num = random.randint(1,100)

while True:
    print "you're guess?"
    g = int(raw_input())
    if g == num:
        break
    if g < num:
        print "that's too small"
    else:
        print "that's too big"
        
print "the number is indeed "+str(num)

yield

def foo():
    yield 1
    yield 7

for x in foo():
    print x

myFilter

def myFilter(func,lst):
    ret = []
    for x in lst:
        if func(x):
            ret += [x]
    return ret

(func,lst) = (lambda x: x%3 == 0, range(1,20))

print myFilter(func,lst)

print filter(func,lst)

split

str1 = 'this is a whole sentence bli blu bla'

words = str1.split() #str1.split('b')

for word in words:
    print word
 


load in interactive mode

 execfile('check.py')


Help

help() module, keyword..

ls

os.listdir('.')

system

system(...) system(command) -> exit_status Execute the command (a string) in a subshell.


which platform?

import sys 
sys.platform
import platform
platform.platform()
platform.system()

args[]

import sys 
print sys.argv[0] # program name 
print sys.argv[1] # first argument  

Installing help

  1. Download html documentation [3] and extract to a directory (say /my/path/python_doc
  2. PYTHONDOCS=/my/path/python_doc; export PYTHONDOCS
  3. Now, the help() command will enable you to enter keywords as well (as modules)

misc

  • pass - do nothing - just for syntax fillings..
if True:
    pass 
#    a = 'hello there'
print 'hello'
Personal tools