{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Python course\n",
"\n",
"Hannes Ovrén\n",
"\n",
"Computer Vision Laboratory
\n",
"Linköping University\n",
"\n",
"[hannes.ovren@liu.se](hannes.ovren@liu.se)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# What is Python?\n",
"\n",
"Wikipedia has this to say:\n",
"\n",
"> Python is a widely used general-purpose, high-level programming language. Its design philosophy emphasizes code readability, and its syntax allows programmers to express concepts in fewer lines of code than would be possible in languages such as C++ or Java. The language provides constructs intended to enable clear programs on both a small and large scale."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Python History\n",
"\n",
"- Roots in the late 80's (Guido van Rossum)
\n",
"- 1994: Version 1.0\n",
"- 2000: Version 2.0\n",
"- 2008: Version 3.0\n",
"- 2010: Version 2.7 (last 2.x release)\n",
"- 2015: Version 3.5 (current stable)\n",
"\n",
"**We will use 3.4+**"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# The language at a glance\n",
"\n",
"- Multiple paradigms\n",
" - Object orientated\n",
" - Functional\n",
" - Procedural\n",
" - ...\n",
"- Dynamic typing\n",
"- Automatic memory management\n",
"- Large standard library"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Python as a script\n",
"\n",
"- Python 3.x: `$ python3 myscript.py`\n",
"- Python 2.x: `$ python myscript.py`
or `$ python2 myscript.py`\n",
"- `python` *should* point to 2.x (but might not)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"### Hashbang\n",
"Add one of the following to the top of the script\n",
"\n",
"- `#!/usr/bin/env python3`\n",
"- `#!/usr/bin/python3`\n",
"\n",
"Run as\n",
"\n",
"`$ ./myscript.py`"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Python REPL\n",
"\n",
"- **R**ead-**E**val-**P**rint-**L**oop\n",
"- Interactive work\n",
"- Direct Interpreter (`$ python3`)\n",
"- IPython\n",
" - history\n",
" - tab-complete\n",
" - ...\n",
"- Jupyter/IPython notebooks\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Hello World!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [],
"source": [
"print('Hello World!')"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Small example"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"for i in range(5):\n",
" if i % 2 == 0:\n",
" print(i, 'is even')\n",
" else:\n",
" print(i, 'is odd')"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Whitespace controls scope!\n",
"\n",
"```python\n",
"for i in range(5):\n",
" if i % 2 == 0:\n",
" print(i, 'is even')\n",
" else:\n",
" print(i, 'is odd')\n",
"```\n",
"\n",
"- **Always** use **4 spaces** for indentation (check your editor settings)\n",
"- Mixing tabs and spaces can lead to problems!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Data types\n",
"\n",
"Most simple data types are built in\n",
"- integers\n",
"- floats\n",
"- strings (unicode)\n",
"- booleans (`True` and `False`)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"x = 1\n",
"y = 2.0\n",
"s = \"Strings are unicode, so we can write in 日本語\"\n",
"b = True\n",
"\n",
"z = int(y)\n",
"z, type(z)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Operators\n",
"- Like usual: +, -, *, %, /\n",
"- Power: **"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"5 ** 2"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"### Logical operators\n",
"- `and`, `or`, `not`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"5 > 3 and not 5 > 7"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- Bitwise operators exist as well"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Range checks"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"x = 5\n",
"3 < x < 7"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Container types\n",
"\n",
"- `list`\n",
"- `tuple`\n",
"- `dict`\n",
"- `set`"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## `list`\n",
"\n",
"- Random access (0-indexed!)\n",
"- Negative numbers count backwards"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"a = [1, 2, 3, 4]\n",
"print(a[0], a[3], a[-1])"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Items can be added or removed"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"a.append(100)\n",
"a.remove(2)\n",
"print(a)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Mix *item types* freely!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"b = [1, 2.0, 'banana', [30, 40]]"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Check if item is in the list using `in`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"'banana' in b"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## `tuple`\n",
"\n",
"- A \"frozen\" list: No `append`, `remove` or altering values\n",
"- Hashable (unlike `list`)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"a = [1, 2, 3, 4]\n",
"t = (1, 2, 3, 4) # tuple\n",
"a[2] = 88 # OK\n",
"\n",
"t[2] = 88"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Iterating over things (naive way)\n",
"\n",
"By using \n",
"- `len(seq)` - number of items in `seq`\n",
"- `range(N)` - generate sequence of integers in half-open interval `[0, N)`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"fruits = ['apple', 'banana', 'kiwi']\n",
"for i in range(len(fruits)):\n",
" print(fruits[i])"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"### Please avoid this!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Iterating over things (better way!)\n",
"We use `for item in sequence` to grab items from sequences like `list` or `tuple`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"fruits = ['apple', 'banana', 'kiwi']\n",
"for fruit in fruits:\n",
" print(fruit)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Slicing\n",
"\n",
"`seq[a:b]` gives the part of the sequence in the *half-open* range `[a, b)`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"fruits = ['oranges', 'apple', 'banana', 'kiwi', 'raspberry']"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"fruits[:2]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"fruits[2:]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"fruits[-3:]"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We can also specify the step length (which can be negative!)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"fruits[1::2]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"fruits[-1::-2]"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Sequence unpacking\n",
"\n",
"Any sequence can be unpacked into separate variables"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"person = ('Hannes', 31, 'CVL')\n",
"name, age, workplace = person\n",
"print(name, 'is', age, 'years old and works at', workplace)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We can also just get some of the values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"name, _, workplace = person\n",
"print(name, workplace)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"name, *rest = person\n",
"print(name, rest)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Unpacking in loops"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"eating_habits = [('monkey', 'bananas'), \n",
" ('horse', 'grass'), \n",
" ('human', 'hamburgers')]\n",
"\n",
"for animal, food in eating_habits:\n",
" print('The', animal, 'eats', food)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"This is equivalent to the less pretty"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"for item in eating_habits:\n",
" print('The', item[0], 'eats', item[1])"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## `set`\n",
"- Accepts mixtures of any kind of *hashable* object\n",
"- Is **unordered**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"things = {5, 2, 1, 1, 1, 1, 'monkey', (1, 3)}\n",
"print(things)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Check for set membership using `in`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"5 in things"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We can add and remove things from sets"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"things.add(7)\n",
"things.remove('monkey')\n",
"things"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Set operations like intersection, union, etc. all exist"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"A = {1, 2, 3, 4, 5}\n",
"B = {1, 4, 10, 20}\n",
"print('Intersection:', A.intersection(B))\n",
"print('Union:', A.union(B))\n",
"print('Difference:', A - B)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Only *hashable types* work. E.g. not `list` objects"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"A.add([1, 2])"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Key-value map: `dict`\n",
"- Access items by **key**\n",
"- Key can be any hashable object (i.e. `tuple` is ok, but not `list`!)\n",
"- Keys in the same dict can have different types"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"country_area = {\n",
" 'Sweden' : 449964,\n",
" 'Italy' : 301338, }\n",
"print('The area of Sweden is', country_area['Sweden'], 'km²')"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"New values/keys can be inserted after creation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"country_area['Germany'] = 357168\n",
"print(country_area)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Extract keys and values using methods `dict.keys()` and `dict.values()`\n",
"- Note that `dict` is an *unordered* container"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"print(country_area.keys())\n",
"print(country_area.values())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Check for key existance with `in`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"'Sweden' in country_area"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Get key-value pairs using `dict.items()`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"for country, area in country_area.items():\n",
" print('The area of', country, 'is', area, 'km²')"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## `dict` as ad-hoc \"classes\" for structured data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"movies = [\n",
" {'name' : 'Star Wars',\n",
" 'year' : 1977,\n",
" 'actors' : ['Mark Hamill', 'Harrison Ford']},\n",
" \n",
" {'name' : 'Alien',\n",
" 'year' : 1979,\n",
" 'actors' : ['Sigourney Weaver',]}\n",
"]\n",
"\n",
"for movie in movies:\n",
" print(movie['name'], 'was released in', movie['year'])"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Functions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def square(x):\n",
" return x ** 2\n",
"\n",
"square(4)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Functions are like any object, and can be used as input to other functions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def apply_func(func, x):\n",
" return func(x)\n",
"\n",
"f = square\n",
"apply_func(f, 3)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"A function can return multiple values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def square_and_cube(x):\n",
" return x ** 2, x ** 3\n",
"\n",
"square, cube = square_and_cube(4)\n",
"print(square, cube)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"This is just creating and unpacking a tuple!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"y = square_and_cube(5)\n",
"print(y, type(y))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Function arguments\n",
"- **keyword** arguments are optional arguments with a default value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def greet(name, greeting='Hello'):\n",
" print(greeting, name)\n",
"\n",
"greet('Hannes')\n",
"greet('Hannes', greeting='Hi')\n",
"greet('Hannes', 'Hi')"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Variable number of arguments\n",
"- For variable number of **positional** arguments\n",
"- `args` will be a tuple of values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def add(*args):\n",
" result = 0\n",
" for x in args: # Not *args!\n",
" result += x\n",
" return result\n",
"\n",
"add(1, 2, 5, 9)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Variable number of **keyword arguments** is also supported\n",
"- `kwargs` will be a dictionary"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def print_thing_length(**kwargs):\n",
" for name, length in kwargs.items(): # Not **kwargs\n",
" print(name, 'is', length, 'tall')\n",
"\n",
"print_thing_length(hannes='182 cm', smurf='two apples')"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"When is this useful?"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Variable number of arguments (cont.)\n",
"- Combining works as expected\n",
"- Ordering of positional, keyword args, and their variable versions is important"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def sum_all_the_things(a, b, *args, foo=5, bar=10, **kwargs):\n",
" result = a + b + foo + bar\n",
" for x in args:\n",
" result += x\n",
" for x in kwargs.values():\n",
" result += x\n",
" return result\n",
"\n",
"sum_all_the_things(1, 0, 0, 0, 0, 0, monkey=100)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## String formatting using `%`\n",
"- `printf`-like format specifiers: \n",
" - %s\n",
" - %d\n",
" - %f\n",
" - ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"'%s (%d) has an IMDB score of %.1f' % ('Alien', 1979, 8.5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Think of this as *deprecated*. Better ways exist!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## String formatting using `str.format()`\n",
"- Very rich formatting language\n",
"- Recommended way to format strings"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"'{movie} ({year}) has an IMDB score of {imdb:.2f}'.format(movie='Alien',\n",
" year=1979, \n",
" imdb=8.5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"'{} ({}) has an IMDB score of {:.1f}'.format('Alien', 1979, 8.5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Supports things like:\n",
" - 0-padding numbers\n",
" - float precision\n",
" - left/right justification"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Mini-assignment\n",
"\n",
"Write a function that takes a list of movies and returns the name and score of the movie with the highest IMDB score.\n",
"\n",
"### Data\n",
"http://users.isy.liu.se/cvl/hanov56/pycourse/"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"movies = [\n",
" {\n",
" 'name' : 'Star Wars',\n",
" 'year' : 1977,\n",
" 'imdb' : 8.7\n",
" },\n",
" \n",
" {\n",
" 'name' : 'Alien',\n",
" 'year' : 1979,\n",
" 'imdb' : 8.5\n",
" },\n",
" \n",
" {\n",
" 'name' : 'The Terminator',\n",
" 'year' : 1984,\n",
" 'imdb' : 8.1\n",
" },\n",
" \n",
" {\n",
" 'name' : 'House of the Dead',\n",
" 'year' : 2002,\n",
" 'imdb' : 2.0\n",
" },\n",
"] "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## My solution\n",
"Batteries included!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"def best_movie(movielist):\n",
" best = max(movielist, key=lambda movie: movie['imdb'])\n",
" return best['name'], best['imdb']\n",
"\n",
"movie, score = best_movie(movies)\n",
"print(\"The best movie is '{}' with a score of {:.1f}\".format(movie, score))"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Classes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from math import pi\n",
"\n",
"class Circle:\n",
" name = 'Circle'\n",
" def __init__(self, radius):\n",
" self.radius = radius\n",
" \n",
" def area(self):\n",
" return pi * self.radius ** 2\n",
"\n",
"c = Circle(2.0)\n",
"print('A circle with radius {} has area {:.2f}'.format(c.radius,\n",
" c.area()))\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- `__init__` is called when the object is initialized (a \"constructor\")\n",
"- `self` $\\approx$ `this` but is **explicit**\n",
"- class members can be declared outside of `__init__`, but don't!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Class inheritance\n",
"- Simply list parent classes\n",
"- `object` is the top level object (can be omitted like previous example)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class Shape(object):\n",
" def print_info(self):\n",
" print('I am a {} with area {:.2f}'.format(self.shape_type,\n",
" self.area()))\n",
"\n",
"class Circle(Shape):\n",
" def __init__(self, radius):\n",
" self.radius = radius\n",
" self.shape_type = 'Circle'\n",
" \n",
" def area(self):\n",
" return pi * self.radius ** 2\n",
"\n",
"c = Circle(2.0)\n",
"c.print_info()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Where are my `public` and `private`??!\n",
"\n",
"- Nowhere: all attributes are \"public\"!\n",
"- \"getters\" and \"setters\" are unneccessary (and *unpythonic*)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"### How about underscores?\n",
"- `'_'` or `'__'` can be used to signal \"privateness\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class A:\n",
" def __init__(self):\n",
" self._my_private = 10\n",
"a = A()\n",
"a._my_private # Hmm??"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": true,
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [],
"source": [
"class A:\n",
" def __init__(self):\n",
" self.__really_private = 10\n",
"\n",
"a = A()\n",
"a.__really_private"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"a._A__really_private"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We can **never make something private**. But we can give hints."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Calling parents methods: `super()`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class CircleWithSquareHole(Circle):\n",
" def __init__(self, radius, hole_side):\n",
" super().__init__(radius) # calls Circle.__init__(self, radius)\n",
" self.side = hole_side\n",
" \n",
" def area(self):\n",
" circle_area = super().area() # calls Circle.area(self)\n",
" return circle_area - self.side ** 2\n",
" \n",
"cwsh = CircleWithSquareHole(2, 1)\n",
"cwsh.area()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Exceptions: handling errors\n",
"\n",
"- Python coding involves a lot of *exception handling*\n",
"- `try` - `except` - `finally` blocks"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"try:\n",
" y = 5 / 0\n",
"except ZeroDivisionError:\n",
" print('Oh no! Divide by zero!')\n",
" y = 0\n",
"finally:\n",
" print('This always executes')\n",
"print('y =', y)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Easier to ask forgiveness than to ask for permission\n",
"Python prefers exception handling over condition checking\n",
"\n",
"#### Example: set value from dict, or to default value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"DEFAULT_VALUE = 1\n",
"d = {'a' : 10, 'b' : 20}\n",
"\n",
"if 'c' in d:\n",
" x = 5\n",
"else:\n",
" x = DEFAULT_VALUE\n",
"print(x)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"source": [
"is equivalent to"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"try:\n",
" x = d['c']\n",
"except KeyError:\n",
" x = DEFAULT_VALUE\n",
"print(x)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## File open example"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"try:\n",
" f = open('/tmp/thisfilereallydoesnotexist', 'r')\n",
" data = f.read()\n",
"except IOError:\n",
" print('Failed to open and read data from file')"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Compare to these pre-checks\n",
"- Does the file exist?\n",
"- Do I have the right permissions?\n",
"- Is there some other error?"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Exceptions (cont.)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Catch multiple exceptions\n",
"\n",
"```python\n",
"try:\n",
" x = some_calculation()\n",
"except (ZeroDivisionError, ValueError):\n",
" x = 0\n",
"```\n",
"\n",
"Catch everything (**avoid if possible**). Why?\n",
"\n",
"```python\n",
"try:\n",
" x = some_calculation()\n",
"except:\n",
" x = 0\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## `lambda` functions\n",
"\n",
"Short *single statement* anonymous functions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"add = lambda a, b: a + b\n",
"add(3, 4)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"### Example: sort by norm"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"alist = [(1, 2), (2,0), (0, 10)]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"sorted(alist, key=lambda x: x[0] ** 2 + x[1] ** 2)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## List-comprehensions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"squares = [x ** 2 for x in range(10)]\n",
"print(squares)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"vehicles = [('SAAB 9-5', 'car'),\n",
" ('Titanic', 'boat'),\n",
" ('Tesla model S', 'car'),\n",
" ('Atlantis', 'spaceship')]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"cars = [name for name, vtype in vehicles if vtype == 'car']\n",
"print(cars)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## List comprehensions (cont.)\n",
"\n",
"```python\n",
"result = [expr(item) for item in sequence \n",
" if condition(item)]\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Example: Loading images\n",
"\n",
"- Assume `files` is a list of filenames in a directory (not only images!)\n",
"- The image files all start with `image_` (e.g. `image_000.png`)\n",
"- We want to convert the images to grayscale\n",
"\n",
"\n",
"```python\n",
"images = [cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
" for image in \n",
" [cv2.imread(fn) for fn in files \n",
" if fn.startswith('image_')\n",
" ]\n",
" ]\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- Nesting too many can hurt readability!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## List comprehensions: `dict`\n",
"We can do the same for `dict`s"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"square_lookup = {x : x ** 2 for x in range(10)}\n",
"square_lookup[7]"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Reading files\n",
"- Use `open()` to create a `File` object.\n",
"- Modes: r, w, a, rb, wb, ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"f = open('/etc/redhat-release', 'r') # Read-only\n",
"data = f.read()\n",
"print('File contents:')\n",
"print(data)\n",
"f.close()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## `File` objects\n",
"- `read()`, `write()`\n",
"- `readlines()`, `writelines()`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"f = open('/etc/passwd', 'r')\n",
"lines = f.readlines()\n",
"for l in lines[:3]:\n",
" print(l)\n",
"f.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Why the extra linebreaks?"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Reading files (cont.)\n",
"Forgot to call `f.close()`?\n",
"\n",
"Either never create the `File` object `f` at all"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"data = open('/etc/redhat-release', 'r').read()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"or use a *context manager*, using `with`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"with open('/etc/redhat-release', 'r') as f:\n",
" data = f.read()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The file is automatically closed after the `with` finishes"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## String manipulation\n",
"Some useful string methods\n",
"- `.split()`\n",
"- `.strip()`\n",
"- `.lower()` / `.upper()`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"s = 'The quick brown fox jumps over the lazy dog'\n",
"words = s.split()\n",
"words[3]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"s.upper()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"' extra whitespace '.strip()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## From list to string\n",
"A list of strings can be turned to a string with `str.join()`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"print('My favourite fruits are', ', '.join(fruits[:3]))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Python modules and packages\n",
"- *package* is a collection of *modules*\n",
"- modules are used via `import`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import time\n",
"print(time)\n",
"print('Current POSIX time:', time.time())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We can also import only specific names from a module using `from ... import ...`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from calendar import isleap, leapdays\n",
"isleap(1984)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Assignment: \n",
"## IMDB movie ratings\n",
"\n",
"See assignment web page for details"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"## Some useful things\n",
"\n",
"- `help(obj)` launches a help section for some object \"obj\", which can be an object instance, a class, a module, function, ...\n",
"- `dir(obj)` lists all attributes of an object\n",
"- `repr(obj)` returns the represenation string for an object"
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}