Booleans


In [ ]:
True and True

In [ ]:
True or False

In [ ]:
bool(1)

In [ ]:
bool(0)

None

None is Python's null value.


In [ ]:
a = None
a is None

In [ ]:
b = 'is something'
b is not None

Control Flow

if statement


In [ ]:
a = 4
if a > 0:
    print('more than 0')

In [ ]:
if a <= 0:
    print('0 or less')
elif a > 0 and a < 10:
    print('more than zero, less than 10')
else:
    print('something else')

There is also a single line version


In [ ]:
<statement if condition True> if <condition> else <otherwise>

In [ ]:
a = -4
print('foo') if a > 0 else print('bar')

for loop

It's called for loop but should have been named for each loop.


In [ ]:
for(<init>; <condition>; <statement>):
    # do something with the index

In [ ]:
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for(i = 0; i < arr.length(); i++):
    print(arr[i])

The Python for loop as a different semantic


In [ ]:
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for item in arr:
    print(item)

In [ ]:
for item in range(10):
    print(item)

break and continue are also available.

while loop

There is a while loop in Python but it is hardly used and generally avoided.


In [ ]:
x = 256
total = 0
while x > 0:
    if total > 500:
        break
    total = total + x # shorthand for this is total += x
    x = x / 2
total

pass statement

pass is the no-op operation.


In [ ]:
def f():
    pass

In [ ]:
f()

Exception handling

Exception handling in Python is similar to exception handling in Java. It follows the same schema:

try:
    thow Exception
catch:
    catch Exception

Note: Advanced Python programmers and Python itself use exception handing not merely for error situations. May be we can come back to this later.

However, the python syntax is slightly different:


In [ ]:
try:
    raise Exception('Some exception')
except:
    print('An exception occured')

A slightly more usefuly example:


In [ ]:
try:
    float('a string')
except ValueError as e:
    print(e)

Sometimes you want to suppress an exception but want some code to be executed regardless whether the code in the try block succeeded or not.


In [ ]:
fh = open('material/foo.py')
try:
    float(fh.read())
except:
    print('an exception occured')
finally:
    fh.close()

Data structures

One of the reasons why Python is so popular is due to its simple, yet powerful data structures. Groking theres is crucial!

Tuple

Tuples are one-dimensional, fixed-length, immutable sequences of objects. The easiest way to create them is the comma-seperated notation:


In [ ]:
a = 1, 2, 3
a

The same can be achived with parentheses.


In [ ]:
a = (1, 2, 3)
a

In general parentheses are not requires. But in some situations they are. Hence, it's pretty common to use them regardless of the situation.

Tuples can also created by using the tuple function.


In [ ]:
a = tuple('foo bar')
a

Individual elements are accessed using the [] notation as with most other sequence types in Python.


In [ ]:
a[0]

In [ ]:
a[0] = 'f'

In [ ]:
a = (1, 'a', [1, 2])
a[2].append(3)
a

Tuples can be concatinated.


In [ ]:
(1, 2) + (2, 3)

In [ ]:
(1, 2) * 3

Unpacking tuples


In [ ]:
tup = 1, 2, 3
tup

In [ ]:
a, b, c = 1, 2, 3
print(a, b, c)

Nested structures can also be unpacked.


In [ ]:
tup = (1, 2, (3, 4))
tup

In [ ]:
a, b, (c, d) = tup
d

tuple methods


In [ ]:
tup.<TAB>

List

Lists are semantically similar to tuples, but in contrast, lists are variable-length and mutable.


In [ ]:
a = [1, 2, 3, None, 'foo']
a

In [ ]:
a.append(1.2e4)
a

In [ ]:
a.insert(2, 'new text')
a

The insert method is computationally intensive and should be avoided


In [ ]:
a.pop(2)

In [ ]:
a

In [ ]:
a.remove(1)
a

The keyword in can be used to check for membership


In [ ]:
3 in a

In [ ]:
1 in a

In [ ]:
[4, 5, 6] + [1, 2, 3]

List methods


In [ ]:
a = [4, 5, 6]
a.extend([1, 2, 3])
a

In [ ]:
a.sort()
a

In [ ]:
b = ['one', 'two', 'three', 'four']
b.sort(key=len)
b

Splicing

To select subsections of array-like objects (like list and tuple) the start:stop indexing operator can be used.


In [ ]:
a = list(range(10))
a

Notice: Python uses 0-based indexing


In [ ]:
a[2:4]

Shorthand versions can be used when be the first index refers to the first element in the sequence or the last index refers to the last element.


In [ ]:
a[:3]

In [ ]:
a[5:]

In [ ]:
a[:]

In [ ]:
b = (2, 3, 4, 5, 6)
b[3:5]

This notation can also be used to assign to a sequence.


In [ ]:
a[:4] = [3, 2, 1, 0]
a

Negative indices can be used to do slicing relative to the end of the list rather than the beginning.


In [ ]:
a[-1] # is the last element of the list

In [ ]:
a[-4:-2]

In [ ]:
Image('images/slicing.png')

There is also an optional step parameter to this. So actually it looks like this start:stop:step.


In [ ]:
a[::1]

In [ ]:
a[::2]

In [ ]:
a[::-2]

In [ ]:
a[::-1]

In [ ]:
a[1:6:2]

Built-in sequence functions

enumerate can be used to keep track of the index while iteration over a sequence.


In [ ]:
words = ['this', 'is', 'a', 'short', 'sentence']
for index, word in enumerate(words):
    print('{} {}'.format(index, word))

sorted does what it sounds like: it sortes sequences.


In [ ]:
sorted('this is a short sentence')

In [ ]:
sorted([(5, 1), (17, 2), (22, 3)], key=lambda x: x[1])

zip pairs up elements of sequences.


In [ ]:
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
for x, y in zip(a, b):
    print(x, y)

In [ ]:
c = [True, False]
for x, y, z in zip(a, b, c):
    print(x, y, z)

In [ ]:
heros = [('Peter', 'Parker'), ('Bruce', 'Wayne'), ('Clark', 'Kent')]
first, last = zip(*heros)
first, last

reversed reverses a sequence.


In [ ]:
list(reversed(range(10)))

Rule of thumb: if you are using index based iteration, you are doing it wrong


In [ ]:
Image('images/youre-doing-it-wrong.jpg')

Dict

dicts are probably the most important data structure in Python. In other languages these objects are called hash maps or associative arrays. They are collections of key-value pairs, which means they don't have an order!
There are several ways to instantiate a dict.


In [ ]:
a = {}
b = {'a': 'foo', 'b': 'bar', 'c': 3}
c = dict(a = 'grok')
b, c

Accessing a dict's elements is done using the same syntax as is used for tuples and lists


In [ ]:
b['a']

In [ ]:
c['a'] = 'bar'

In [ ]:
c['a']

To check whether a key is a dict, the in syntax can be used.


In [ ]:
'a' in c

In [ ]:
'c' in c

Elements can be remove by using the del keyword or the pop method. The latter return the object that will be deleted.


In [ ]:
b

In [ ]:
del b['c']

In [ ]:
b

In [ ]:
b.pop('b')

In [ ]:
b

Adding objects is also very intuitive.


In [ ]:
b['b'] = 2
b

Multiple values can be added simultaneously by joining two dicts, using the update method.


In [ ]:
b.update({'c': 3, 'd': 4})
b

The keys and values methods return all keys and values.


In [ ]:
b.keys()

In [ ]:
b.values()

While the values of a dict can be any Python object, the keys need to be immutable like int, float, string or tuple. The elements of a tuple must also be immutable. This is called hashability.
Object's hashability can be checked with the build-in hash function.


In [ ]:
print(hash(412))
print(hash(412.431))
print(hash('this is a string'))

In [ ]:
hash([1, 2, 3])

To use a list as key, it can be converted to a tuple.


In [ ]:
hash(tuple([1, 2, 3]))

Set

A set is an unorderer collection of unique elements.
They can be created using two different ways.


In [ ]:
set([1, 2, 3, 3, 4])

In [ ]:
set((1, 2, 3, 3, 4))

In [ ]:
set('Python is great!')

In [ ]:
{1, 2, 3, 3, 4}

Sets support mathematical set operations like union, intersection, differences and symmetric difference.


In [ ]:
a = {1, 2, 3, 4, 5}
b = {3, 4, 5, 6, 7, 8}

a | b # union (or)
#a.union(b)

In [ ]:
Image('images/Union.png')

In [ ]:
a & b # intersection (and)
#a.intersection(b)

In [ ]:
Image('images/Intersection.png')

In [ ]:
a ^ b # symmetric difference (xor)
#a.symmetric_difference(b)

In [ ]:
Image('images/symDifference.png')

In [ ]:
a - b # difference
#a.difference(b)

In [ ]:
Image('images/Difference.png')

It can also be checked if a set is a super or sub set of another set


In [ ]:
a_set = {1, 2, 3, 4, 5}
{1, 2, 3}.issubset(a_set)

In [ ]:
a_set.issuperset({1, 2, 3})

Two sets are equal if their contents are equal


In [ ]:
{1, 2, 3} == {3, 2, 1}

Other useful methods are


In [ ]:
a.add(x)           # Add element x to the set a
a.remove(x)        # Remove element x from the set a
a.isdisjoint(b)    # True if a and b have no elements in common.

List, Set, and Dict Comprehensions

List comprehensions are one of the most-loved Python language features. They allow you to concisely form a new list by filtering the elements of a collection and transforming the elements passing the filter in one conscise expression. They take the basic form:

[expr for val in collection if condition]

which is equvalent to the follwoing for loop:

result = []
for val in collection:
    if condition:
        result.append(expr)

The condition is optional, which leaves us with a simpler expression:

[expr for val in collection]

They make for a concise writing and thus easier reading and writing (once learned :-) ).


In [ ]:
[word.lower() for word in 'This is a simple sentence'.split()]

In [ ]:
[word.lower() for word in 'This is a simple sentence'.split() if len(word) < 3]

In [ ]:
results = []
for word in 'This is a simple sentence'.split():
    if len(word) < 3:
        results.append(word.lower())
results

Similarly dicts and sets can be created.


In [ ]:
{num: num + 1 for num in range(10)}

In [ ]:
{num for num in range(10)}

List comprehensions can also be nested.


In [ ]:
physicists = [
    ['Albert', 'Paul', 'Marie', 'Richard'],
    ['Einstein', 'Dirac', 'Curie', 'Feynman']
]
physicists

In [ ]:
[[name.upper() for name in physicist] for physicist in physicists]