Introduction¶
Goals¶
This guide will explain some basic python concepts through a series of exercises. However, it’s far from complete and cannot teach you Python. You should read the The Python Tutorial and use the Library Reference whenever necessary.
Humble Beginnings¶
You don’t need type declarations. To create a variable simply assign to it:
width = 10
To use functions from modules use the import
keyword:
import math
a = math.sqrt(7)
help(math.sqrt)
print int(a)
The most common data structure in Python is the list (similar to the C++
std::vector
, but without type constraints):
x = [1, 2]
a, b = x
assert a == 1
assert b == 2
x.append(3)
print [1, 2, 3]
assert len(x) == 3
Another common data structure is the tuple (an immutable list):
x = (1, 2)
assert x[1] == 2
Lists, tuples and strings are sequences. More information about sequences can be found in Sequence Types.
In contrast with C and Java, Python uses indentation to delimit blocks:
x = 1
if x == 0:
print 'zero'
elif x % 2:
print 'odd'
else:
print 'even'
Indented blocks are always preceded by a statement which ends in a colon
(:
). You should always use 4 spaces for indentation (PEP8).
Python has a bool()
type with two values: True
and False
.
You can also use any sequence as a boolean value in if
or while
conditions (empty sequences are False
, non-empty sequences are
True
).
To iterate over a sequence you can use the for
statement:
l = [1, 3, 5]
for x in l:
print x
If you just want to iterate over a range of integers, you can create with the
range()
function:
assert range(3) == [0, 1, 2]
assert range(1, 3) == [1, 2]
for i in range(len(l)):
print "l[%d] = %d" % (i, l[i])
This could be also written as:
for idx, val in enumerate(l):
print "l[%d] = %d" % (idx, val)
To define a function use def
:
def even(x):
return x % 2 == 0
If you don’t explicitly return
from a function, the caller will receive the
special value None
.
You can have a variable number of arguments:
def csv(*args):
return ', '.join(args)
print csv('a', 'b', 'c')
You can also call a function with arguments from a list object:
print csv(*['a', 'b', 'c'])
Functional Style¶
If you want to write code in a functional style, you have access to the usual tools:
However Python also provides list comprehensions to replace map()
and
filter()
with a syntax closer to the mathematical set notation:
f1 = filter(lambda x: x % 2 == 0, range(10))
f2 = [x for x in range(10) if x % 2 == 0]
assert f1 == f2
mf1 = map(lambda x: x*x, filter(lambda x: x % 2 == 0, range(10)))
mf2 = [x*x for x in range(10) if x % 2 == 0]
assert mf1 == mf2
List comprehensions can have multiple for
and if
clauses:
print [(x, y) for x in range(3) for y in range(3)]
Something Useful¶
The Python equivalent of C/C++ NULL
is None
. You should always use
the is
(or is not
) operator to compare things with None
. is
tests for object identity (think of it as pointer comparison).
You can get a sub-sequence from a sequence using the slice notation:
a = range(10)
assert a[1:3] == range(1, 3)
You can omit one or both ends of the slice range, which means the beginning or the end of the sequence is used:
assert a[:3] == range(3)
assert a[3:] == range(3, 10)
assert a[:] == a
Note that the return value of a slice is a shallow copy:
assert a[:] is not a
Negative indexes count backwards from the end of the sequence:
assert a[-1] == a[9]
assert a[-3:] == range(7, 10)
Exercise¶
Implement binary search using a recursive function. The function definition should start with:
def bsearch(l, x):
where x is the element being searched and l is the list. The return value
must satisfy l[bsearch(l, x)] == x
or be None
if x is not found in l.
You can use slicing to avoid defining a helper function.
Unit test:
def test_bsearch():
assert bsearch([], 0) is None
assert bsearch([0], 0) == 0
assert bsearch([0], 1) is None
for i in range(11):
assert bsearch(range(11), i) == i
Mappings¶
Another important built-in data type is dict
, similar to the C++
std::map
or the Java HashMap
:
emptydict = {}
specs = {'color': 'black', 'size': 3.5}
If the keys are strings that conform to Python identifier naming rules, you can
use the dict
constructor to avoid quoting them:
specs = dict(color='black', size=3.5)
assert len(specs) == 2
assert specs['color'] == 'black'
print specs['price']
# raise a KeyError exception if the key is not found
print spec.get('price')
# return None if key is not found
assert 'color' in specs
assert 'price' not in specs
del specs['color']
assert 'color' not in specs
specs['color'] = 'green'
print specs.keys()
print specs.values()
print list(specs.iteritems())
for k, v in specs.iteritems():
print k, '=', v
You can call a function by specifying the name of some parameters together with their value (keyword arguments):
def print_report(rows, columns, color='red'):
print "A %s report with %d rows and %d columns" % (color, rows, columns)
print_report(1, 1)
print_report(1, 1, 'black')
print_report(color='blue', columns=10, rows=2)
A function can receive variable keyword arguments (kwargs is a
dict
):
def map2str(**kwargs):
tmp = ["%s=%s" % (str(k), str(v)) for k, v in kwargs.iteritems()]
return ', '.join(tmp)
print map2str(size=10, color='black')
def apply_function(f, *args, **kwargs):
return f(*args, **kwargs)
Exercise¶
Write a word counter function.
-
word_count
(text, case_sensitive=True)¶
The return value should be a dict
which maps (whitespace-separated)
words to the number of occurrences in text.
Hint: read the documentation for String Methods and
dict
.
Unit test:
def test_word_count():
assert word_count("a b c") == dict(a=1, b=1, c=1)
assert word_count("a b a") == dict(a=2, b=1)
assert word_count("a b A") == dict(a=1, b=1, A=1)
assert word_count("a b A", False) == dict(a=2, b=1)