Python Course 2: Intermediate Python

Functions

Functions encapsulate repeatable code. They're defined with the def keyword


In [26]:
def say_hello():
    print('hello, world!')

Functions are invoked using parenthesis (). Argumements are passed between the parenthesis.


In [27]:
say_hello()


hello, world!

In [28]:
def hi(name):
    print('hi', name)

hi("pythonistas")


hi pythonistas

Functions can use the return keyword to stop execution and send a value back to the caller.


In [29]:
def double(value):
    return value*2

print(double(4))


8

exercise Write a function, stars that takes a number and returns that number of * (asterisk).

print(stars(5))
*****

In [33]:
"abcde"[:2]


Out[33]:
'ab'

Lists

This data type orders elements using a 0-based index.


In [3]:
empty_list = []
list_with_numbers = [0, 1, 2, 3, 4, 5, 6]
list_with_mixed = ["zero", 1, "TWO", 3, 4, "FIVE", "Six"]

Any type of element, including functions and other lists, can be stored in a list.


In [4]:
list_with_lists = ["this", "contains", "a", ["list", "of", ["lists"] ]]

def some_func(message):
    print('message is ', message)

list_with_function = [some_func]

# Let's call the function
list_with_function[0]('hello from a list')


message is  hello from a list

Lists are a class of data structure called iterables that allow for easily going over all the elements of the list


In [35]:
iter_example = ['a', 'b', 'c', 'd', 'e']

for elem in iter_example:
    print(elem)


a
b
c
d
e

List Comprehension

Lists can be created using list comprehension, which puts for loops inside brackets, capturing the results as a list.

The format is [x for x in iter_example]

Slicing

Slicing allows for the selection of elements from a list.

a[start:end] # items start through end-1
a[start:]    # items start through the rest of the array
a[:end]      # items from the beginning through end-1
a[:]         # a copy of the whole array

There is also the step value, which can be used with any of the above:

a[start:end:step] # start through not past end, by step

The key point to remember is that the :end value represents the first value that is not in the selected slice. So, the difference beween end and start is the number of elements selected (if step is 1, the default).

The other feature is that start or end may be a negative number, which means it counts from the end of the array instead of the beginning. So:

a[-1]    # last item in the array
a[-2:]   # last two items in the array
a[:-2]   # everything except the last two items

Similarly, step may be a negative number:

a[::-1]    # all items in the array, reversed
a[1::-1]   # the first two items, reversed
a[:-3:-1]  # the last two items, reversed
a[-3::-1]  # everything except the last two items, reversed

exercise Write a function that takes a string and returns the reverse of it.

reverse('abcde')  # returns `edcba`

Sets

Sets are like lists except they cannot have duplicate elements.


In [39]:
list_with_dupes = [1, 2, 3, 3, 4, 5]

print(set(list_with_dupes)) #removes duplicate 3


{1, 2, 3, 4, 5}

Dictionaries (dicts)

dictionaries key and value pairs. they let you store data with an object that you can use to look up the value. They're constructed using the curly brace {}


In [45]:
a_dict = {'some': 'value', 'another': 'value'}

print(a_dict['another'])


value

The dictionary works by calculating the hash of the key. You can see this using the __hash__ function.


In [51]:
'another'.__hash__()


Out[51]:
-6012119028048823898

Any value that is hashable can be used as a key, including numbers.


In [53]:
mixed_keys = {4 : 'somevalue'}
print(mixed_keys[4])


somevalue

In [ ]:
New elements will be added or changed just by referencing them. The `del` word will delete entries.

In [55]:
changing_dict = {'foo': 'bar', 'goner': "gone soon"}

changing_dict['foo'] = 'biv' #update existing value
changing_dict['notfound'] = 'found now!' #insert new value
del changing_dict['goner'] #removes key / value

print(changing_dict)


{'foo': 'biv', 'notfound': 'found now!'}

In [ ]:
You can iterate over keys in the dictionary using a for loop

In [56]:
starter_dictionary = {'a': 1, 'b': 2, 'c': 3}

for key in starter_dictionary:
    print(key)


a
b
c

You can iterate over the values using the values() method.


In [58]:
for val in starter_dictionary.values():
    print(val)


1
2
3

We'll cover these if there's time

Classes

Classes encapsulate data and functions. They're a handy abstraction in many languages such as Java and C++. They're used in python but not as often as functions. Create them using the class keyword.


In [60]:
class ExampleClass:
    pass

ex = ExampleClass() #construct an instance of the ExampleClass

Unit Testing


In [8]:
# foo.py
def foo():
    return 42

In [23]:
# test_foo.py
import unittest

class TestFoo(unittest.TestCase):
    
    def test_foo_returns_42(self):
        expected = 42
        actual = foo()
        self.assertTrue(expected == actual)

# Below doesn't work in a jupyter notebook        
# if __name__ == '__main__':
#     unittest.main()

In [21]:
if __name__ == '__main__':
    unittest.main(argv=['first-arg-is-ignored'], exit=False)


.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

In [ ]: