Skip to content

Instantly share code, notes, and snippets.

@xamgore
Created October 22, 2017 22:05
Show Gist options
  • Save xamgore/53e4ed712d2d0c63cb32ac4172bc5418 to your computer and use it in GitHub Desktop.
Save xamgore/53e4ed712d2d0c63cb32ac4172bc5418 to your computer and use it in GitHub Desktop.
Python. Семинар 2.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Python. Семинар 2"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Модуль itertools"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль itertools: islice\n",
"\n",
"* Функции из модуля itertools позволяют легко выражають самые разнообразные операции над последовательностями.\n",
"\n",
"* Настоятельно рекомендуется ознакомится с [документацией](https://docs.python.org/3.6/library/itertools.html) по этому модулю.\n",
"\n",
"* Функция islice обобщает понятие слайса на произвольный итератор:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 2]"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from itertools import islice\n",
"\n",
"xs = range(10)\n",
"list(islice(xs, 3)) # ≡ xs[:3]"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[3, 4, 5, 6, 7, 8, 9]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(islice(xs, 3, None)) # ≡ xs[3:]"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[3, 5, 7]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(islice(xs, 3, 8, 2)) # ≡ xs[3:8:2]"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль itertools: бесконечные итераторы\n",
"\n",
"* Реализуем функцию take, которая строит список из не более, чем n первых элементов переданного ей итератора:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 2]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def take(n, iterable):\n",
" return list(islice(iterable, n))\n",
"\n",
"take(3, range(10))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Названия бесконечных итераторов говорят сами за себя:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[0, 5, 10]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from itertools import count, cycle, repeat\n",
"\n",
"take(3, count(0, 5))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[1, 2, 3]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"take(3, cycle([1, 2, 3]))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[42, 42, 42]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"take(3, repeat(42))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[42, 42]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"take(3, repeat(42, 2)) # не совсем ∞"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль itertools: dropwhile и takewhile\n",
"\n",
"* Функции dropwhile и takewhile обобщают логику функций drop и take на произвольный предикат\n",
"\n",
"* Обратите внимание, что обе функции возвращают итератор, а не список, как реализованная нами функция take:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[5, 6, 7, 8, 9]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from itertools import dropwhile, takewhile\n",
"\n",
"list(dropwhile(lambda x: x < 5, range(10)))"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"<itertools.takewhile at 0x7f1c786f2f48>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"it = takewhile(lambda x: x < 5, range(10))\n",
"it"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 2, 3, 4]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(it)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль itertools: chain\n",
"\n",
"* В модуле itertools реализован уже знакомый нам генератор chain, который конкатенирует произвольное число итераторов:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 5, 6, 7]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from itertools import chain\n",
"\n",
"take(5, chain(range(2), range(5, 10)))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Сконкатенировать итератор итераторов можно с помощью метода chain.from_iterable:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[2, 3, 3, 4, 5]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"it = (range(x, x ** x) for x in range(2, 4))\n",
"take(5, chain.from_iterable(it))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль itertools: tee\n",
"\n",
"* Функция tee создаёт n независимых копий переданного ей итератора:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"([0, 1, 2], [0, 1, 2], [0, 1, 2])"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from itertools import tee\n",
"\n",
"it = range(3)\n",
"a, b, c = tee(it, 3)\n",
"list(a), list(b), list(c)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Использовать it после копирования не рекомендуется, потому что в этом случае скопированные итераторы a, b, c могут пропустить элемент:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"([], [])"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"it = iter(range(3))\n",
"a, b = tee(it, 2)\n",
"used = list(it)\n",
"list(a), list(b)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль itertools: комбинаторные итераторы\n",
"\n",
"В модуле itertools в виде итераторов реализованы полезные комбинаторные операции, например:"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* декартово произведение итераторов"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[('A', 'A'), ('A', 'B'), ('B', 'A'), ('B', 'B')]"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from itertools import product\n",
"\n",
"list(product(\"AB\", repeat=2))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* перестановки элементов итератора"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[('A', 'B'), ('B', 'A')]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from itertools import permutations\n",
"\n",
"list(permutations(\"AB\"))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* сочетания (с повторениями и без) из элементов итератора"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"([('A', 'B'), ('A', 'C'), ('B', 'C')],\n",
" [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')])"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from itertools import combinations, combinations_with_replacement\n",
"\n",
"list(combinations(\"ABC\", 2)), list(combinations_with_replacement(\"ABC\", 2))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Элементы функционального программирования"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функторы\n",
"\n",
"* Python __не__ функциональный язык, но в нём есть элементы функционального программирования.\n",
"\n",
"* Функторы - это классы с определённым оператором ()\n",
"\n",
"* В Python - с реализованным методом \\_\\_call\\_\\_"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"10"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"class Functor:\n",
" def __call__(self, value):\n",
" return 2 * value\n",
" \n",
"f = Functor()\n",
"f(5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функторы. Пример №1"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"21"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"class mulN:\n",
" def __init__(self, n):\n",
" self.n = n\n",
" \n",
" def __call__(self, value):\n",
" return self.n * value\n",
" \n",
"f = mulN(7)\n",
"f(3)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функторы. Пример №2"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"class logger:\n",
" def __init__(self, filename):\n",
" self.file = open(filename, 'a')\n",
" \n",
" def __call__(self, message):\n",
" self.file.write(message + '\\n')\n",
" \n",
" def close(self):\n",
" self.file.close()\n",
" \n",
"l = logger(\"log.txt\")\n",
"l(\"Message\")\n",
"l.close()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функторы. Пример №3"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"first: 5, second: 7\n"
]
}
],
"source": [
"def f(a, b):\n",
" print(\"first: {}, second: {}\".format(a, b))\n",
" \n",
"class currying:\n",
" def __init__(self, func, param):\n",
" self.func = func\n",
" self.param = param\n",
" \n",
" def __call__(self, param):\n",
" return self.func(self.param, param)\n",
" \n",
"c = currying(f, 5)\n",
"c(7)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Анонимные функции\n",
"\n",
"* Анонимные функции имеют вид\n",
"```python\n",
"lambda arguments: expression\n",
"```\n",
"и эквивалентны по поведению\n",
"```python\n",
"def <lambda>(arguments):\n",
" return expression\n",
"```\n",
"\n",
"* Всё, сказанное про аргументы именованных функций, справедливо и для анонимных\n",
"```python\n",
"lambda foo, *args, bar=None, **kwargs: 42\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Анонимные функции. Пример №1"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"10"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(lambda x: 2 * x)(5)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"18"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def double(x):\n",
" return 2 * x\n",
"\n",
"c = 10\n",
"\n",
"f = lambda x: double(x) + c\n",
"f(4)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[(13, -3), (4, 1), (1, 2), (9, 10)]"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"xs = [(1, 2), (4, 1), (9, 10), (13, -3)]\n",
"xs.sort(key=lambda x: x[1])\n",
"xs"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Анонимные функции. Пример №2"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'zero'"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def f(x):\n",
" if x == 0:\n",
" return \"zero\"\n",
" elif x == 1:\n",
" return \"one\"\n",
" else:\n",
" return \"other\"\n",
"\n",
"f(0)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'zero'"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f = lambda x: x == 0 and \"zero\" or x == 1 and \"one\" or \"other\"\n",
"\n",
"f(0)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Анонимные функции. Пример №3"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2\n",
"1\n"
]
}
],
"source": [
"def f(k):\n",
" while k > 0:\n",
" print(k)\n",
" k -= 1\n",
"\n",
"f(2)"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2\n",
"1\n"
]
},
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def my_print(x):\n",
" print(x)\n",
" return x\n",
"\n",
"f = lambda k: k and my_print(k) and f(k - 1)\n",
"\n",
"f(2)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Замыкания\n",
"\n",
"* Замыкание - функция, сохраняющая необходимые данные.\n",
"\n",
"* Что делать, если функция зависит от большого числа параметров?\n",
"\n",
" * Передавать их в функцию при каждом вызове - неудобно\n",
" \n",
" * Создать глобальные переменные для части параметров, использовать их в функции «засорение» глобального пространства имен, может привести к ошибкам.\n",
" \n",
" * ... Хотелось бы, чтобы экземпляр функции «запоминал» свои параметры."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Замыкания. Пример №1"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"50"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"N = 10\n",
"\n",
"def mulN(i, n=N):\n",
" return n * i\n",
"\n",
"mulN(5)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"50"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"N = 55\n",
"mulN(5)"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"275"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f = lambda i, n=N: n * i\n",
"f(5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"При создании анонимная функция (как и обычная функция) запоминает значение параметров по умолчанию"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Замыкания. Пример №1"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"#### Вариант №2 - фабрика функций"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"def mulN(n):\n",
" return lambda i: n * i"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"14"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mul2 = mulN(2)\n",
"mul2(7)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"24"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mulN(3)(8)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Замыкания. Пример №2"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"def logger_factory(filename):\n",
" f = open(filename, \"a\")\n",
" \n",
" def logger(message):\n",
" f.write(message + \"\\n\")\n",
" return f\n",
" \n",
" return logger\n",
"\n",
"logger = logger_factory(\"log.txt\")\n",
"f = logger(\"MESSAGE\")\n",
"f.close()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Замыкания. Пример №3"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"first: 5, second: 7\n"
]
}
],
"source": [
"def f(a, b):\n",
" print(\"first: {}, second: {}\".format(a, b))\n",
"\n",
"def currying(func, f_param):\n",
" def function(s_param):\n",
" return func(f_param, s_param)\n",
" \n",
" return function\n",
"\n",
"func = currying(f, 5)\n",
"func(7)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функции высших порядков\n",
"\n",
"* Функции, принимающие в качестве параметра другие функции\n",
"\n",
"* Например:\n",
"\n",
" * map\n",
" \n",
" * filter\n",
" \n",
" * zip\n",
" \n",
" * partial\n",
" \n",
" * reduce"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функции высших порядков: map\n",
"\n",
"* map(function, iterable [...]) --> map object\n",
"\n",
"* Возвращает итератор по значениям, полученным применением функции function к элементам одной или нескольких последовательностей."
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 8, 27, 64]"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def cube(x):\n",
" return x * x * x\n",
" \n",
"list(map(cube, range(5)))"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 8, 27, 64]"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(map(lambda x: x * x * x, range(5)))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функции высших порядков: map"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[5, 20, 21]"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = [5, 2, 7]\n",
"y = (1, 10, 3)\n",
"list(map(lambda x, y: x * y, x, y))"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[5, 10, 7]"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y = (1, 10, 3, 1)\n",
"list(map(max, x, y))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"В Python 2 более короткая последовательность дополнялась None. В Python 3 вычисления прекращаются как только кончается самая короткая последовательность."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функции высших порядков: filter\n",
"\n",
"* filter(function, iterable) --> filter object\n",
"\n",
"* Возвращает iterator по элементам последовательности, для которых предикат function вернул true"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[4, 6, 8]"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"xs = [1, 4, 6, 7, 8, 9]\n",
"list(filter(lambda x: x % 2 == 0, xs))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Вместо предиката можно передать None, в этом случае в последовательности останутся только truthy значения"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[42]"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"xs = [0, None, [], {}, set(), \"\", 42]\n",
"list(filter(None, xs))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функции высших порядков: zip\n",
"\n",
"* zip(iterable [...]) --> zip object\n",
"\n",
"* Строит последовательность кортежей из элементов нескольких последовательностей"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[(1, 'one', '!'), (2, 'two', '@'), (3, 'three', '#')]"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a = range(1, 10)\n",
"b = (\"one\", \"two\", \"three\")\n",
"c = {\"!\" : 1, \"@\" : 2, \"#\" : 3}\n",
"result = list(zip(a, b, c))\n",
"result"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[(1, 2, 3), ('one', 'two', 'three'), ('!', '@', '#')]"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(zip(*result))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Поведение в случае последовательностей различной длины аналогично map."
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[('a', 0), ('b', 1), ('c', 2)]"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(zip(\"abc\", range(10)))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Замечание: генераторы списков, множеств и словарей\n",
"\n",
"* В Python есть генераторы списков, множеств и словарей:"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[1, 9, 25, 49, 81]"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"[x ** 2 for x in range(10) if x % 2 == 1]"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{1, 2, 5, 6}"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{x % 7 for x in [1, 9, 16, -1, 2, 5]}"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{0: 0, 1: 1, 2: 4, 3: 9}"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{x: x ** 2 for x in range(4)}"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Функции map и filter можно было бы определить как-то так:\n",
"```python\n",
"def map(function, *iterable):\n",
" return (function(*x) for x in zip(*iterable))\n",
"```\n",
"```python\n",
"def filter(function, iterable):\n",
" return (x for x in iterable if function(x))\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функции высших порядков: partial\n",
"\n",
"* partial(function, *args, *\\*keywords) --> function'\n",
"\n",
"* С помощью partial можно зафиксировать часть позиционных и ключевых аргументов в функции\n",
"\n",
"* объявлена в модуле functools"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[('b', 2), ('a', 4)]"
]
},
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from functools import partial\n",
"\n",
"f = partial(sorted, key=lambda p: p[1])\n",
"f([(\"a\", 4), (\"b\", 2)])"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[1, 2, 3, 4]"
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g = partial(sorted, [2, 3, 1, 4])\n",
"g()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функции высших порядков: reduce\n",
"\n",
"* reduce(function, iterable[, initial]) --> value\n",
"\n",
"* Возвращает значение, полученное последовательным применением бинарной функции function к элементам последовательности и результату предыдущего вычисления.\n",
"\n",
"* объявлена в модуле functools"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"1914"
]
},
"execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from functools import reduce\n",
"\n",
"reduce(lambda acc, d: 10 * acc + int(d), \"1914\", 0)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Функции высших порядков: модуль operators\n",
"\n",
"* Модуль operators содержит множество функций, относящихся к операторам Python. Например, operator.add(x, y) эквивалентно выражению x + y.\n",
"\n",
"* Имена функций использую имена специальных классовых методов (прим. \\_\\_add\\_\\_). Варианты без префикса и суффикса \\_\\_ также имеются.\n",
"\n",
"| Operation | Syntax | Function |\n",
"|:---------------- |:--------------- |:------------------------- |\n",
"| Addition | a + b | add(a, b) |\n",
"| Containment Test | obj in seq | contains(seq, obj) |\n",
"| Identity | a is b | is\\_(a, b) |\n",
"| Indexing | obj[k] | getitem(obj, k) |\n",
"| Slicing | seq[i:j] | getitem(seq, slice(i, j)) |\n",
"| ... | ... | ... |"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Менеджеры контекстов"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Типичная работа с файлом"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Менеджеры контекста позволяют компактно выразить паттерн управления ресурсами. "
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"file = open(\"python2.ipynb\")\n",
"try:\n",
" # ... do something\n",
" data = file.read()\n",
" # ... do something else\n",
"finally:\n",
" file.close()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* С помощью менеджера контекста пример выше можно записать так:"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"with open(\"python2.ipynb\") as file:\n",
" # ... do something\n",
" data = file.read()\n",
" # ... do something else"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Метод close будет вызван автоматически, вызывать его явно не нужно."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Как работает with?"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"__enter__\n",
"__body__\n",
"__exit__\n"
]
}
],
"source": [
"class Sample(object):\n",
" def __enter__(self):\n",
" print(\"__enter__\")\n",
" \n",
" def __exit__(self, type, value, trace):\n",
" print(\"__exit__\")\n",
" \n",
"with Sample() as sample:\n",
" print(\"__body__\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Метод \\_\\_enter\\_\\_ инициализирует контекст, например, открывает файл или захватывает мьютекс\n",
"\n",
"* Метод \\_\\_exit\\_\\_ вызывается после выполнения тела оператора with\n",
"\n",
"* Экземпляр любого класса, реализующего эти два метода, является менеджером контекста"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Как работает with?"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Значение, возвращаемое методом \\_\\_enter\\_\\_, записывается по имени, указанному после оператора as."
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"ename": "AttributeError",
"evalue": "'NoneType' object has no attribute 'do_something'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-56-d4ebf0f99a20>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mSample\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0msample\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0msample\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdo_something\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'do_something'"
]
}
],
"source": [
"class Sample(object):\n",
" def __enter__(self):\n",
" pass # Oops...\n",
" \n",
" def __exit__(self, type, value, trace):\n",
" pass\n",
" \n",
" def do_something(self):\n",
" print(\"do something\")\n",
" \n",
"with Sample() as sample:\n",
" sample.do_something()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Как работает with?"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"enter\n",
"do something\n",
"exit\n"
]
}
],
"source": [
"class Sample(object):\n",
" def __enter__(self):\n",
" print(\"enter\")\n",
" return self\n",
" \n",
" def __exit__(self, type, value, trace):\n",
" print(\"exit\")\n",
" \n",
" def do_something(self):\n",
" print(\"do something\")\n",
" \n",
"with Sample() as sample:\n",
" sample.do_something()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Управление ресурсами"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<__main__.Resource object at 0x7f1c786d46d8>\n",
"Resource.free()\n"
]
}
],
"source": [
"class Resource(object):\n",
" def free(self):\n",
" print(\"Resource.free()\")\n",
" \n",
"class ResourceManager(object):\n",
" def __init__(self, resource):\n",
" super(ResourceManager, self).__init__()\n",
" self.resource = resource\n",
"\n",
" def __enter__(self):\n",
" return self.resource\n",
"\n",
" def __exit__(self, type, value, trace):\n",
" self.resource.free()\n",
" \n",
"with ResourceManager(Resource()) as resource:\n",
" print(resource)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Метод \\_\\_exit\\_\\_\n",
"\n",
"* Метод \\_\\_exit\\_\\_ принимает три аргумента:\n",
" 1. тип исключения,\n",
" 2. само исключение и\n",
" 3. объект типа traceback."
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"class Resource(object):\n",
" def __enter__(self):\n",
" pass\n",
" \n",
" def __exit__(self, type, value, trace):\n",
" print(\"Exception {} of type {} occured\".format(value, type))"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Exception Oops... of type <class 'Exception'> occured\n"
]
},
{
"ename": "Exception",
"evalue": "Oops...",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mException\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-60-fe441fb1e3c5>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mResource\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mresource\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Oops...\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mException\u001b[0m: Oops..."
]
}
],
"source": [
"with Resource() as resource:\n",
" raise Exception(\"Oops...\")"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Exception None of type None occured\n"
]
}
],
"source": [
"with Resource() as resource:\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Метод \\_\\_exit\\_\\_\n",
"\n",
"* Если в процессе исполнения тела оператора with былоподнятно исключение, метод \\_\\_exit\\_\\_ может подавить его, вернув True."
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"class Resource(object):\n",
" def __enter__(self):\n",
" pass\n",
" \n",
" def __exit__(self, type, value, trace):\n",
" print(\"Exception {} of type {} occured\".format(value, type))\n",
" return True"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Exception Oops... of type <class 'Exception'> occured\n"
]
}
],
"source": [
"with Resource() as resource:\n",
" raise Exception(\"Oops...\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Несколько ресурсов сразу\n",
"\n",
"* Оператор with позволяет работать с несколькими контекстными менеджерами одновременно:"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A.__enter__\n",
"B.__enter__\n",
"B.__exit__\n",
"A.__exit__\n"
]
}
],
"source": [
"class A:\n",
" def __enter__(self):\n",
" print(\"A.__enter__\")\n",
" return self\n",
" \n",
" def __exit__(self, type, value, trace):\n",
" print(\"A.__exit__\")\n",
"\n",
"class B:\n",
" def __enter__(self):\n",
" print(\"B.__enter__\")\n",
" \n",
" def __exit__(self, type, value, trace):\n",
" print(\"B.__exit__\")\n",
" \n",
"with A() as a, B() as b:\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Можно также использовать оператор with без указания имени переменной:"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A.__enter__\n",
"A.__exit__\n"
]
}
],
"source": [
"with A():\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Примеры менеджеров контекста: syncronized"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"import threading\n",
"\n",
"class synchronized:\n",
" def __init__(self):\n",
" self.lock = threading.Lock()\n",
" \n",
" def __enter__(self):\n",
" self.lock.acquire()\n",
" \n",
" def __exit__(self, *exc_info):\n",
" self.lock.release()\n",
" \n",
"with synchronized():\n",
" pass # do something"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Примеры менеджеров контекста: cd"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"/home/misha/Dropbox/Temp/class/python/2017/python2\n",
"/tmp\n"
]
}
],
"source": [
"import os\n",
"\n",
"class cd:\n",
" def __init__(self, path):\n",
" self.path = path\n",
" \n",
" def __enter__(self):\n",
" self.saved_cwd = os.getcwd()\n",
" os.chdir(self.path)\n",
" \n",
" def __exit__(self, *exc_info):\n",
" os.chdir(self.saved_cwd)\n",
" \n",
"print(os.getcwd())\n",
"with cd(\"/tmp\"):\n",
" print(os.getcwd())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль contextlib"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль contextlib: closing\n",
"\n",
"* Менеджер контекста closing обобщает логику уже известного нам opened на экземпляр любого класса, реализующего метод close.\n",
"\n",
"* Реализовать closing самому несложно, но приятно, когда в стандартной библиотеке языка есть и такие мелочи.\n",
"\n",
"* С помощью closing можно, например, безопасно работать с HTTP ресурсами:"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"from contextlib import closing\n",
"from urllib.request import urlopen\n",
"\n",
"with closing(urlopen(\"http://www.python.org\")) as page:\n",
" pass # do somethin\n",
"# page.close() called"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль contextlib: redirect_stdout\n",
"\n",
"* Менеджер контекста redirect_stdout позволяет локально перехватывать вывод в стандартный поток\n",
"\n",
"* Пример использования:"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'Hello, World!\\n'"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from contextlib import redirect_stdout\n",
"import io\n",
"\n",
"handle = io.StringIO()\n",
"with redirect_stdout(handle):\n",
" print(\"Hello, World!\")\n",
"\n",
"handle.getvalue()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль contextlib: suppress\n",
"\n",
"* С помощью менеджера контекста suppress можно локального подавить исключения указанных типов:"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"from contextlib import suppress\n",
"\n",
"with suppress(FileNotFoundError):\n",
" os.remove(\"example.txt\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* При использовании suppress, как и в целом при работе с исключениями, стоит указывать наиболее специфичный тип исключения."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Модуль collections"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль collection: defaultdict\n",
"\n",
"* defaultdict - словарь с функцией-инициализатором:"
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"defaultdict(list,\n",
" {'Ahmed': ['Silver'],\n",
" 'Ali': ['Blue', 'Black'],\n",
" 'Arham': ['Green'],\n",
" 'Yasoob': ['Yellow', 'Red']})"
]
},
"execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from collections import defaultdict\n",
"\n",
"colours = (\n",
" ('Yasoob', 'Yellow'),\n",
" ('Ali', 'Blue'),\n",
" ('Arham', 'Green'),\n",
" ('Ali', 'Black'),\n",
" ('Yasoob', 'Red'),\n",
" ('Ahmed', 'Silver'),\n",
")\n",
"\n",
"favourite_colours = defaultdict(list)\n",
"\n",
"for name, colour in colours:\n",
" favourite_colours[name].append(colour)\n",
" \n",
"favourite_colours"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль collection: OrderedDict\n",
"\n",
"* Порядок ключей в обычном словаре не определён:"
]
},
{
"cell_type": "code",
"execution_count": 93,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"['foo', 'boo']"
]
},
"execution_count": 93,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d = dict([(\"foo\", \"bar\"), (\"boo\", 42)])\n",
"list(d)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* OrderedDict — словарь с ключами, упорядоченными по времени добавления:"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"['foo', 'boo']"
]
},
"execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from collections import OrderedDict\n",
"\n",
"d = OrderedDict([(\"foo\", \"bar\"), (\"boo\", 42)])\n",
"list(d)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль collection: counter\n",
"\n",
"* Тип Counter - это специализация словаря для подсчёта объектов, которые можно захешировать:"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Counter({'bar': 1, 'foo': 4})"
]
},
"execution_count": 74,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from collections import Counter\n",
"\n",
"c = Counter([\"foo\", \"foo\", \"foo\", \"bar\"])\n",
"c[\"foo\"] += 1\n",
"c"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Счётчик поддерживает все методы словаря, а также реализует несколько дополнительных:"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"c.pop(\"foo\")"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"c[\"boo\"] # не поднимает исключение"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль collection: counter\n",
"\n",
"* Метод elements перечисляет элементы счётчика в произвольном порядке. Элементы, для которых частота равна нулю или отрицательна, игнорируются:"
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"['foo', 'foo', 'foo', 'foo']"
]
},
"execution_count": 77,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"c = Counter(foo=4, bar=-1)\n",
"list(c.elements())"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" * Метод most_common возвращает заданное число самых частых элементов:"
]
},
{
"cell_type": "code",
"execution_count": 78,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"[('foo', 4)]"
]
},
"execution_count": 78,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
" c.most_common(1)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" * Методы substract и update позволяют поэлементно обновить значения счётчика:"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Counter({'bar': 0, 'foo': 4})"
]
},
"execution_count": 79,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"c.update([\"bar\"])\n",
"c"
]
},
{
"cell_type": "code",
"execution_count": 80,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Counter({'bar': 0, 'foo': 2})"
]
},
"execution_count": 80,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"c.subtract({\"foo\": 2})\n",
"c"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль collection: deque\n",
"\n",
"* Тип deque реализует двустороннюю очередь\n",
" \n",
"* Добавление и удаление элемента с обеих сторон очереди работает за константное время, индексирование — за время, линейное от размера очереди."
]
},
{
"cell_type": "code",
"execution_count": 81,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"deque([0, 1, 2, 3])"
]
},
"execution_count": 81,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from collections import deque\n",
" \n",
"q = deque([1, 2, 3])\n",
"q.appendleft(0)\n",
"q"
]
},
{
"cell_type": "code",
"execution_count": 82,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"deque([0, 1, 2, 3, 4])"
]
},
"execution_count": 82,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"q.append(4)\n",
"q"
]
},
{
"cell_type": "code",
"execution_count": 83,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 83,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"q.popleft()"
]
},
{
"cell_type": "code",
"execution_count": 84,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 84,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"q[0]"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль collection: deque\n",
"\n",
"* Конструктор deque принимает опциональный аргумент maxlen, ограничивающий максимальную длину очереди\n",
"\n",
"* При добавлении элемента к ограниченной очереди лишние элементы \"вываливаются\" с противоположной стороны:"
]
},
{
"cell_type": "code",
"execution_count": 85,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"deque([0, 1])"
]
},
"execution_count": 85,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"q = deque([1, 2], maxlen=2)\n",
"q.appendleft(0)\n",
"q"
]
},
{
"cell_type": "code",
"execution_count": 86,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"deque([1, 2])"
]
},
"execution_count": 86,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"q.append(2)\n",
"q"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Модуль collection: namedtuple\n",
"\n",
"* Функция namedtuple возвращает тип кортежа, специализированный на фиксированное множество полей:"
]
},
{
"cell_type": "code",
"execution_count": 87,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"('name', 'age')"
]
},
"execution_count": 87,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from collections import namedtuple\n",
"\n",
"Person = namedtuple(\"Person\", [\"name\", \"age\"])\n",
"p = Person(\"George\", age=77)\n",
"p._fields"
]
},
{
"cell_type": "code",
"execution_count": 88,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"('George', 77)"
]
},
"execution_count": 88,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p.name, p.age"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Несколько полезных методов при работе с именованными кортежами:"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"OrderedDict([('name', 'George'), ('age', 77)])"
]
},
"execution_count": 89,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p._asdict()"
]
},
{
"cell_type": "code",
"execution_count": 90,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Person(name='Bill', age=77)"
]
},
"execution_count": 90,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p._replace(name=\"Bill\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Конец"
]
}
],
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment