diff --git a/arithmetic.ipynb b/arithmetic.ipynb deleted file mode 100644 index ba393c2..0000000 --- a/arithmetic.ipynb +++ /dev/null @@ -1,926 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# Арифметические операции\n", - "\n", - " \n", - "**С.В. Лемешевский** (email: `sergey.lemeshevsky@gmail.com`), Институт математики НАН Беларуси\n", - "\n", - "\n", - "Язык Python , благодаря наличию огромного количества библиотек для решения\n", - "разного рода вычислительных задач, является конкурентом таким пакетам как Matlab и\n", - "Octave. Запущенный в интерактивном режиме, он, фактически, превращается в\n", - "мощный калькулятор. В этой главе речь пойдет об арифметических операциях,\n", - "доступных в данном языке.\n", - "\n", - "Как было сказано в предыдущей главе, посвященной типам и модели данных\n", - "Python, в этом языке существует три встроенных числовых типа данных:\n", - "* целые числа (`int`);\n", - "\n", - "* вещественные числа (`float`);\n", - "\n", - "* комплексные числа (`complex`).\n", - "\n", - "Если в качестве операндов некоторого арифметического выражения используются\n", - "только целые числа, то результат тоже будет целое число. Исключением является\n", - "операция деления, результатом которой является вещественное число.\n", - "При совместном использовании целочисленных и вещественных переменных, результат\n", - "будет вещественным.\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "# Арифметические операции с целыми и вещественными числами\n", - "
\n", - "\n", - "Все эксперименты будем проводить в Python, запущенном в интерактивном\n", - "режиме.\n", - "\n", - "\n", - "**Сложение.** Складывать можно непосредственно сами числа ..." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "3 + 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "либо переменные, но они должны предварительно быть проинициализированы." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = 3\n", - "b = 2\n", - "a + b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Результат операции сложения можно присвоить другой переменной..." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = 3\n", - "b = 2\n", - "c = a + b\n", - "print (c)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "либо ей же самой, в таком случае можно использовать полную или сокращенную\n", - "запись, полная выглядит так:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = 3\n", - "b = 2\n", - "a = a + b\n", - "print (a)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "сокращенная так:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = 3\n", - "b = 2\n", - "a += b\n", - "print (a)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Все перечисленные выше варианты использования операции сложения могут быть\n", - "применены для всех нижеследующих операций.\n", - "\n", - "**Вычитание.**" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "4 - 2" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = 5\n", - "b = 7\n", - "a - b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Деление.**" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "9 / 3" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = 7\n", - "b = 4\n", - "a / b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Получение целой части от деления.**" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "9 // 3" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = 7\n", - "b = 4\n", - "a // b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Получение дробной части от деления.**" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "9 % 5" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = 7\n", - "b = 4\n", - "a % b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Возведение в степень.**" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "5**4" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = 4\n", - "b = 3\n", - "a**b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "\n", - "\n", - "\n", - "# Работа с комплексными числами\n", - "
\n", - "\n", - "Для создания комплексного числа можно использовать функцию `complex(a, b)`, в\n", - "которую, в качестве первого аргумента, передается действительная часть, в качестве\n", - "второго – мнимая. Либо записать число в виде `a+bj`.\n", - "\n", - "Рассмотрим несколько примеров.\n", - "\n", - "Создание комплексного числа." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "z = 1+2j\n", - "print(z)" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x = complex(3, 2)\n", - "print(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Комплексные числа можно складывать, вычитать, умножать, делить и возводить в\n", - "степень." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x+z" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x-z" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x*z" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x/z" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x**z" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x**3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "У комплексного числа можно извлечь действительную и мнимую части." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x = 3+2j\n", - "x.real" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x.imag" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Для получения комплексносопряженного число необходимо использовать метод\n", - "`conjugate()`." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "x.conjugate()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "\n", - "\n", - "\n", - "# Битовые операции\n", - "
\n", - "\n", - "В Python доступны битовые операции, их можно производить над целыми числами.\n", - "\n", - "**Побитовое И (AND).**" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "p = 9\n", - "q = 3\n", - "p & q" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Побитовое ИЛИ (OR).**" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "p | q" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Побитовое Исключающее ИЛИ (XOR).**" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "p^q" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Инверсия.**" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "~p" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Сдвиг вправо и влево.**" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "p<<1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "\n", - "\n", - "\n", - "# Представление чисел в других системах счисления\n", - "
\n", - "\n", - "В своей повседневной жизни мы используем десятичную систему исчисления, но\n", - "при программирования, очень часто, приходится работать с шестнадцатеричной,\n", - "двоичной и восьмеричной.\n", - "\n", - "**Представление числа в шестнадцатеричной системе.**" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "m = 124504\n", - "hex(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Представление числа в восьмеричной системе.**" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "oct(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Представление числа в двоичной системе.**" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "bin(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "\n", - "\n", - "\n", - "# Библиотека (модуль) `math`\n", - "
\n", - "\n", - "В стандартную поставку Python входит библиотека math , в которой содержится\n", - "большое количество часто используемых математических функций.\n", - "\n", - "Для работы с данным модулем его предварительно нужно импортировать." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import math" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Рассмотрим наиболее часто используемые функции.\n", - "\n", - "**Функция `math.ceil(x)`.**\n", - "\n", - "Возвращает ближайшее целое число большее, чем `x`." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.ceil(3.2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Функция `math.fabs(x)`.**\n", - "\n", - "Возвращает абсолютное значение числа." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.fabs(-7)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Функция `math.factorial(x)`.**\n", - "\n", - "Вычисляет факториал `x`." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.factorial(5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "** Функция `math.floor(x)`.**\n", - "\n", - "Возвращает ближайшее целое число меньшее, чем `x`." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.floor(3.2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Функция `math.exp(x)`.**\n", - "Вычисляет `e**x`." - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.exp(3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Функция `math.log2(x)`.**\n", - "Логарифм по основанию `2`." - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.log2(8)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Функция `math.log10(x)`.**\n", - "\n", - "Логарифм по основанию 10." - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.log10(1000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Функция `math.log(x[, base])`.**\n", - "\n", - "По умолчанию вычисляет логарифм по основанию `e`, дополнительно можно указать\n", - "основание логарифма." - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.log(5)" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.log()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Функция `math.pow(x, y)`.**\n", - "\n", - "Вычисляет значение `x` в степени `y`." - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.pow(3 , 4)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Функция `math.sqrt(x)`.**\n", - "\n", - "Корень квадратный от `x`." - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "math.sqrt(25)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Тригонометрические функции, их мы оставим без примера.**\n", - "\n", - "* `math.cos(x)`\n", - "\n", - "* `math.sin(x)`\n", - "\n", - "* `math.tan(x)`\n", - "\n", - "* `math.acos(x)`\n", - "\n", - "* `math.asin(x)`\n", - "\n", - "* `math.atan(x)`\n", - "\n", - "И напоследок пару констант.\n", - "* `math.pi` — число $\\pi$.\n", - "\n", - "* `math.e` — число $e$.\n", - "\n", - "Помимо перечисленных, модуль `math` содержит ещё много различных\n", - "функций, за более подробной информацией можете обратиться eна\n", - "официальный сайт ().\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/collections.ipynb b/collections.ipynb new file mode 100644 index 0000000..3cd433e --- /dev/null +++ b/collections.ipynb @@ -0,0 +1,1907 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Тыпы коллекций\n", + "\n", + " \n", + "**С.В. Лемешевский** (email: `sergey.lemeshevsky@gmail.com`), Институт математики НАН Беларуси\n", + "\n", + "Date: **Mar 2, 2020**\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Рассматриваются кортежи и списки, а также новые типы коллекций, включая словари и множества.\n", + "\n", + "# Последовательности\n", + "
\n", + "\n", + "Последовательности – это один из типов данных, поддерживающих\n", + "оператор проверки на вхождение (`in`), функцию определения размера\n", + "(`len()`), оператор извлечения срезов (`[]`) и возможность выполнения\n", + "итераций. В языке Python имеется пять встроенных типов\n", + "последовательностей: `bytearray`, `bytes`, `list`, `str` и\n", + "`tuple`. Ряд дополнительных типов последовательностей реализован в\n", + "стандартной библиотеке; наиболее примечательным \n", + "из них является тип `collections.namedtuple`. При выполнении итераций\n", + "все эти последовательности гарантируют строго определенный порядок\n", + "следования элементов.\n", + "\n", + "Строки мы уже рассматривали выше, а в этом разделе познакомимся с\n", + "кортежами, именованными кортежами и списками.\n", + "\n", + "## Кортежи\n", + "
\n", + "\n", + "Кортеж – это упорядоченная последовательность из нуля или более ссылок\n", + "на объекты. Кортежи поддерживают тот же синтаксис получения срезов,\n", + "что и строки. Это упрощает извлечение элементов из кортежа. Подобно\n", + "строкам, кортежи относятся к категории неизменяемых объектов, поэтому\n", + "мы не можем замещать или удалять какие-либо их элементы. Если нам\n", + "необходимо иметь возможность изменять упорядоченную\n", + "последовательность, то вместо кортежей можно просто использовать\n", + "списки или, если в программе уже используется кортеж, который\n", + "нежелательно модифицировать, можно преобразовать кортеж в список с\n", + "помощью функции преобразования `list()` и затем изменять полученный\n", + "список.\n", + "\n", + "Тип данных `tuple` может вызываться как функция `tuple()` – без\n", + "аргументов она возвращает пустой кортеж, с аргументом типа tuple\n", + "возвращает поверхностную копию аргумента; в случае, если аргумент\n", + "имеет другой тип, выполняется попытка преобразовать его в объект\n", + "типа `tuple`. Эта функция принимает не более одного аргумента. Кроме\n", + "того, кортежи могут создаваться без использования функции\n", + "`tuple()`. Пустой кортеж создается с помощью пары пустых круглых\n", + "скобок `()`, а кортеж, состоящий из одного или более элементов, может быть\n", + "создан с помощью запятых. Иногда кортежи приходится заключать в\n", + "круглые скобки, чтобы избежать синтаксической\n", + "неоднозначности. Например, чтобы передать кортеж `1, 2, 3` в функцию,\n", + "необходимо использовать такую форму записи: `function((1, 2, 3))`.\n", + "\n", + "\n", + "\n", + "
\n", + "![Позиции элементов в кортеже](fig-collections/seq_1.png)\n", + "\n", + "\n", + "На рис. [collections:seq:fig:1](#collections:seq:fig:1) показан кортеж\n", + "`t = \"venus\", – 28, \"green\", \"21\", 19.74` и индексы элементов внутри кортежа. Строки\n", + "индексируются точно так же, но, если в строках каждой позиции\n", + "соответствует единственный символ, то в кортежах каждой позиции\n", + "соответствует единственная ссылка на объект.\n", + "\n", + "Кортежи предоставляют всего два метода: `t.count(x)`, который\n", + "возвращает количество объектов `x` в кортеже `t`, и `t.index(x)`,\n", + "который возвращает индекс самого первого (слева) вхождения объекта `x`\n", + "в кортеж `t` или возбуждает исключение `ValueError`, если объект `x`\n", + "отсутствует в кортеже. (Эти методы имеются также и у списков.)\n", + "\n", + "Кроме того, кортежи могут использоваться с оператором `+`\n", + "(конкатенации), `*` (дублирования) и `[]` (получения среза), а\n", + "операторы `in` и `not in` могут применяться для проверки на\n", + "вхождение. Можно использовать также комбинированные операторы\n", + "присваивания `+=` и `*=`. Несмотря на то, что кортежи являются\n", + "неизменяемыми объектами, при выполнении этих операторов интерпретатор\n", + "Python создает за кулисами новый кортеж с результатом операции и\n", + "присваивает ссылку на него объекту, расположенному слева от оператора,\n", + "то есть используется тот же самый прием, что и со строками. Кортежи\n", + "могут сравниваться с помощью стандартных операторов сравнения (`<`,\n", + "`<=`, `==`, `!=`, `>=`, `>`), при этом сравнивание производится\n", + "поэлементно (и рекурсивно, при наличии вложенных элементов, таких как\n", + "кортежи в кортежах).\n", + "\n", + "Рассмотрим несколько примеров получения срезов, начав с извлечения\n", + "единственного элемента и группы элементов:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "hair = \"black\", \"brown\", \"blonde\", \"red\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "hair[2]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "hair[-3:] # то же, что и hair[1:]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Эта операция выполняется точно так же, как и в случае со строками,\n", + "списками или любыми другими последовательностями." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "hair[:2], \"gray\", hair[2:]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Здесь мы попытались создать новый кортеж из 5 элементов, но в\n", + "результате получили кортеж с тремя элементами, содержащий два\n", + "двухэлементных кортежа. Это произошло потому, что мы применили\n", + "оператор запятой к трем элементам (кортеж, строка и кортеж). Чтобы\n", + "получить единый кортеж со всеми этими элементами, необходимо выполнить\n", + "конкатенацию кортежей:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "hair[:2] + (\"gray\",) + hair[2:]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Чтобы создать кортеж из одного элемента, необходимо поставить запятую,\n", + "но если запятую просто добавить, будет получено исключение `TypeError`\n", + "(так как интерпретатор будет думать, что выполняется конкатенация\n", + "строки и кортежа), поэтому необходимо использовать запятую и круглые\n", + "скобки.\n", + "\n", + "Коллекции допускают возможность вложения с любой глубиной\n", + "вложенности. Оператор извлечения срезов `[]` может применяться для\n", + "доступа к вложенным коллекциям столько раз, сколько это будет\n", + "необходимо. Например:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "things = (1, -7.5, (\"pea\", (5, \"Xyz\"), \"queue\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "things[2][1][1][2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Кортежи могут хранить элементы любых типов, включая другие коллекции,\n", + "такие как кортежи и списки, так как на самом деле кортежи хранят\n", + "ссылки на объекты. Использование сложных, вложенных структур данных,\n", + "таких, как показано ниже, легко может создавать путаницу. Одно из\n", + "решений этой проблемы состоит в том, чтобы давать значениям индексов\n", + "осмысленные имена. Например:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "MANUFACTURER, MODEL, SEATING = (0, 1, 2)\n", + "MINIMUM, MAXIMUM = (0, 1)\n", + "aircraft = (\"Airbus\", \"A320-200\", (100, 220))\n", + "aircraft[SEATING][MAXIMUM]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "В первых двух строках вышеприведенного фрагмента мы выполнили\n", + "присваивание кортежам. Когда справа от оператора присваивания\n", + "указывается последовательность (в данном случае – это кортежи),\n", + "а слева указан кортеж, мы говорим, что последовательность справа\n", + "*распаковывается*. Операция распаковывания последовательностей\n", + "может использоваться для организации обмена значений между\n", + "переменными, например:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "a, b = (b, a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Именованные кортежы\n", + "
\n", + "\n", + "Именованные кортежи ведут себя точно так же, как и обычные кортежи, и\n", + "не уступают им в производительности. Отличаются они возможностью\n", + "ссылаться на элементы кортежа не только по числовому индексу, но и по\n", + "имени, что в свою очередь позволяет создавать сложные агрегаты из\n", + "элементов данных.\n", + "\n", + "В модуле `collections` имеется функция `namedtuple()`. Эта функция\n", + "используется для создания собственных типов кортежей. Например:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import collections\n", + "Sale = collections.namedtuple(\"Sale\", \"productid customerid date quantity price\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Первый аргумент функции `collections.namedtuple()` – это имя\n", + "создаваемого кортежа. Второй аргумент – это строка имен, разделенных\n", + "пробелами, для каждого элемента, который будет присутствовать в этом\n", + "кортеже. Первый аргумент и имена во втором аргументе должны быть\n", + "допустимыми идентификаторами языка Python. Функция возвращает класс\n", + "(тип данных), который может использоваться для создания именованных\n", + "кортежей. Так, в примере выше мы можем интерпретировать имя `Sale` как\n", + "имя любого другого класса (такого как `tuple`) в языке Python и\n", + "создавать объекты типа `Sale`. Например:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "sales = []\n", + "sales.append(Sale(432, 921, \"2008-09-14\", 3, 7.99))\n", + "sales.append(Sale(419, 874, \"2008-09-15\", 1, 18.49))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "В этом примере мы создали список из двух элементов типа `Sale`, то\n", + "есть из двух именованных кортежей. Мы можем обращаться к элементам\n", + "таких кортежей по их индексам – например, обратиться к элементу\n", + "`price` в первом элементе списка `sales` можно с помощью выражения\n", + "`sales[0][-1]` (вернет значение `7.99`) – или по именам, которые\n", + "делают программный код более удобочитаемым:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "total = 0\n", + "for sale in sales:\n", + " total += sale.quantity*sale.price\n", + "print(\"Total {0:.2f}\".format(total))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Очень часто простоту и удобство, которые предоставляют именованные\n", + "кортежи, можно обратить на пользу делу. Например, ниже приводится\n", + "версия примера `aircraft` из предыдущего подраздела, имеющая более\n", + "аккуратный вид:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "Aircraft = collections.namedtuple(\"Aircraft\", \"manufacturer model seating\")\n", + "Seating = collections.namedtuple(\"Seating\", \"minimum maximum\")\n", + "aircraft = Aircraft(\"Airbus\", \"A320-200\", Seating(100, 220))\n", + "aircraft.seating.maximum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Списки\n", + "
\n", + "\n", + "Список – это упорядоченная последовательность из нуля\n", + "или более ссылок на объекты. Списки поддерживают тот\n", + "же синтаксис получения срезов, что и строки с кортежами. Это упрощает\n", + "извлечение элементов из списка. В отличие от строк и кортежей списки\n", + "относятся к категории изменяемых объектов, поэтому мы можем замещать\n", + "или удалять любые их элементы. Кроме того, существует возможность\n", + "вставлять, замещать и удалять целые срезы списков.\n", + "\n", + "Тип данных `list` может вызываться как функция `list()` –\n", + "без аргументов она возвращает пустой список, с аргументом типа `list`\n", + "возвращает поверхностную копию аргумента; в случае, если аргумент\n", + "имеет другой тип, выполняется попытка преобразовать его в объект типа\n", + "`list`. Эта функция принимает не более одного аргумента. Кроме того,\n", + "списки могут создаваться без использования функции `list()`. Пустой\n", + "список создается с помощью пары пустых квадратных скобок `[]`, а список,\n", + "состоящий из одного или более элементов, может быть создан с помощью\n", + "последовательности элементов, разделенных запятыми, заключенной в\n", + "квадратные скобки. Другой способ создания списков заключается в\n", + "использовании генераторов списков – эта тема будет рассматриваться\n", + "ниже в этом подразделе.\n", + "\n", + "Поскольку все элементы списка в действительности являются ссылками на\n", + "объекты, списки, как и кортежи, могут хранить элементы любых типов\n", + "данных, включая коллекции, такие как списки и кортежи. Списки могут\n", + "сравниваться с помощью стандартных операторов сравнения (`<`, `<=`,\n", + "`==`, `!=`, `>=`, `>`), при этом сравнивание производится поэлементно\n", + "(и рекурсивно, при наличии вложенных элементов, таких как списки или\n", + "кортежи в списках).\n", + "\n", + "В результате выполнения операции присваивания\n", + "`L = [ – 17.5, \"kilo\", 49, \"V\", [\"ram\", 5, \"echo\"], 7]` мы получим\n", + "список, как показано на рис. [collections:seq:fig:2](#collections:seq:fig:2)\n", + "\n", + "\n", + "\n", + "
\n", + "![Позиции элементов в списке](fig-collections/seq_2.png)\n", + "\n", + "\n", + "К спискам, таким как `L`, мы можем применять оператор извлечения\n", + "среза, повторяя его столько раз, сколько потребуется для доступа к\n", + "элементам в списке, как показано ниже:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "L[0] == L[-6] == -17.5\n", + "L[1] == L[-5] == 'kilo'\n", + "L[1][0] == L[-5][0] == 'k'\n", + "L[4][2] == L[4][-1] == L[-2][2] == L[-2][-1] == 'echo'\n", + "L[4][2][1] == L[4][2][-3] == L[-2][-1][1] == L[-2][-1][-3] == 'c'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Списки, как и кортежи, могут вкладываться друг в друга; допускают\n", + "выполнение итераций по их элементам и извлечение срезов. Все примеры с\n", + "кортежами, которые приводились в предыдущем подразделе, будут работать\n", + "точно так же, если вместо кортежей в них будут использованы\n", + "списки. Списки поддерживают операторы проверки на вхождение `in` и\n", + "`not in`, оператор конкатенации `+`, оператор расширения `+=` (то есть\n", + "добавляет операнд справа в конец списка) и операторы дублирования `*`\n", + "и `*=`. Списки могут также использоваться в качестве аргументов\n", + "функции `len()`.\n", + "\n", + "Кроме того, списки предоставляют методы, перечисленные в\n", + "табл. [collections:seq:tbl:1](#collections:seq:tbl:1) \n", + "\n", + "\n", + "## Таблица 1 : Методы списков
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Синтаксис Описание
L.append(x) Добавляет элемент x в конец списка L
L.count(x) Возвращает число вхождений элемента x в список L
L.extend(m) или L += m Добавляет в конец списка L все элементы итерируемого объекта m
L.index(x, start, end) Возвращает индекс самого первого (слева) вхождения элемента x в список L (или в срез start:end списка L); в противном случае возбуждает исключение ValueError
L.insert(i, x) Вставляет элемент x в список L в позицию int i
L.pop() Удаляет самый последний элемент из списка L и возвращает его в качестве результата
L.pop(i) Удаляет из списка L элемент с индексом int i и возвращает его в качестве результата
L.remove(x) Удаляет самый первый (слева) найденный элемент x из списка L или возбуждает исключение ValueError, если элемент xне будет найден
L.reverse() Переставляет в памяти элементы списка в обратном порядке
L.sort() Сортирует список в памяти. Этот метод принимает те же необязательные аргументы key и reverse что и встроенная функция sorted()`
\n", + "\n", + "\n", + "Несмотря на то, что для доступа к элементам списка можно использовать\n", + "оператор извлечения среза, тем не менее в некоторых ситуациях бывает\n", + "необходимо одновременно извлечь две или более частей списка. \n", + "Сделать это можно с помощью операции распаковывания\n", + "последовательности. Любой итерируемый объект (списки, кортежи и\n", + "другие) может быть распакован с помощью оператора распаковывания\n", + "«звездочка» (`*`). Когда слева от оператора присваивания указывается\n", + "две или более переменных, одна из которых предваряется символом `*`,\n", + "каждой переменной присваивается по одному элементу списка, а\n", + "переменной со звездочкой присваивается оставшаяся часть списка. Ниже\n", + "приводится несколько примеров выполнения распаковывания списков:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "first, *rest = [9, 2, -4, 8, 7]\n", + "first, rest" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "first, *mid, last = \"Charles Philip Arthur George Windsor\".split()\n", + "first, mid, last" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "*directories, executable = \"/usr/local/bin/gvim\".split(\"/\")\n", + "directories, executable" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Когда используется оператор распаковывания последовательности,\n", + "как в данном примере, выражение `*rest` и подобные ему называются\n", + "*выражениями со звездочкой*.\n", + "\n", + "В языке Python имеется также похожее понятие *аргументов со звездочкой*.\n", + "Например, допустим, что имеется следующая функция, принимающая три\n", + "аргумента:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def product(a, b, c):\n", + " return a * b * c" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "тогда мы можем вызывать эту функцию с тремя аргументами или\n", + "использовать аргументы со звездочкой:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "product(2, 3, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "L = [2, 3, 5]\n", + "product(*L)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "product(2, *L[1:])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "В первом примере функция вызывается, как обычно, с тремя\n", + "аргументами. Во втором вызове использован аргумент со звездочкой; в\n", + "этом случае список из трех элементов распаковывается оператором `*`,\n", + "так что функция получает столько аргументов, сколько ей\n", + "требуется. Того же эффекта можно было бы добиться при использовании\n", + "кортежа с тремя элементами. В третьем вызове функции первый аргумент\n", + "передается традиционным способом, а другие два – посредством\n", + "применения операции распаковывания двухэлементного среза списка `L`. \n", + "\n", + "Имеется возможность выполнять итерации по элементам списка с помощью\n", + "конструкции `for item in L:`. Если в цикле потребуется изменять\n", + "элементы списка, то можно использовать следующий прием:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for i in range(len(L)):\n", + " L[i] = process(L[i])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> **Замечание.**\n", + ">\n", + "> Встроенная функция `range()` возвращает целочисленный\n", + "> итератор. С одним целочисленным аргументом, `n`, итератор `range()`\n", + "> возвращает последовательность чисел $0$, $1$, ..., $n-1$.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Этот прием можно использовать для увеличения всех элементов в списке\n", + "целых чисел. Например:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for i in range(len(numbers)):\n", + " numbers[i] += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Генераторы списков\n", + "\n", + "
\n", + "\n", + "Небольшие списки часто создаются как литералы, но длинные списки\n", + "обычно создаются программным способом. Списки целых чисел могут\n", + "создаваться с помощью выражения `list(range(n))`; когда необходим\n", + "итератор целых чисел, достаточно функции `range()`; а для создания\n", + "списков других типов часто используется оператор цикла `for ... in`.\n", + "Предположим, например, что нам требуется получить список високосных\n", + "годов в определенном диапазоне. Для начала мы могли бы использовать\n", + "такой цикл:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "leaps = []\n", + "for year in range(1900, 1940):\n", + " if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):\n", + " leaps.append(year)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Когда функции `range()` передаются два целочисленных\n", + "аргумента `n` и `m`, итератор возвращает последовательность целых\n", + "чисел `n`, `n+1`, ..., `m–1`. \n", + "\n", + "Конечно, если диапазон известен заранее, можно было\n", + "бы использовать литерал списка, например,\n", + "`leaps = [1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936]`.\n", + "\n", + "*Генератор списков* – это выражение и цикл с дополнительным условием,\n", + "заключенное в квадратные скобки, в котором цикл используется для\n", + "создания элементов списка, а условие используется для исключения\n", + "нежелательных элементов. В простейшем виде генератор списков\n", + "записывается, как показано ниже:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```Python\n", + " [item for item in iterable]\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Это выражение вернет список всех элементов объекта `iterable` и\n", + "семантически ничем не отличается от выражения\n", + "`list(iterable)`. Интересными генераторы списков делают две\n", + "особенности – они могут использоваться как выражения и они допускают\n", + "включение условной инструкции, вследствие чего мы получаем две\n", + "типичные синтаксические конструкции использования генераторов списков:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```Python\n", + " [expression for item in iterable]\n", + " [expression for item in iterable if condition]\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Вторая форма записи эквивалентна циклу:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```Python\n", + " temp = []\n", + " for item in iterable:\n", + " if condition:\n", + " temp.append(expression)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Обычно выражение `expression` является либо самим элементом `item`,\n", + "либо некоторым выражением с его участием. Конечно, генератору\n", + "списков не требуется временная переменная `temp[]`, которая необходима\n", + "в версии с циклом `for ... in`.\n", + "\n", + "Теперь можно переписать программный код создания списка високосных\n", + "годов с использованием генератора списка. Мы сделаем это в три\n", + "этапа. Сначала создадим список, содержащий все годы в указанном\n", + "диапазоне:" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "leaps = [y for y in range(1900, 1940)]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "То же самое можно было бы сделать с помощью выражения\n", + "`leaps = list(range(1900, 1940))`. Теперь добавим простое условие,\n", + "которое будет оставлять в списке только каждый четвертый год:" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "leaps = [y for y in range(1900, 1940) if y % 4 == 0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "И, наконец, получаем окончательную версию:" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "leaps = [y for y in range(1900, 1940)\n", + " if (y % 4 == 0 and y % 100 != 0) or (y % 400 == 0)]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Использование генератора списков в данном случае позволило уменьшить\n", + "объем программного кода с четырех строк до двух – не так много, но в\n", + "крупных проектах суммарная экономия может оказаться весьма\n", + "существенной. \n", + "\n", + "Так как генераторы списков воспроизводят списки, то есть итерируемые\n", + "объекты, и сами генераторы списков используют итерируемые объекты,\n", + "имеется возможность вкладывать генераторы списков друг \n", + "в друга. Это эквивалентно вложению циклов `for ... in`. Например, если\n", + "бы нам потребовалось сгенерировать список всех возможных кодов одежды\n", + "для разных полов, разных размеров и расцветок, но исключая одежду для\n", + "полных женщин, нужды и чаянья которых индустрия моды нередко\n", + "игнорирует, мы могли бы использовать вложенные циклы\n", + "`for ... in`, как показано ниже:" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "codes = []\n", + "for sex in \"MF\":\n", + " for size in \"SMLX\":\n", + " \tif sex == \"F\" and size\n", + "\t continue\n", + " for color in \"BGW\":\n", + "\t codes.append(sex + size + color)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Этот фрагмент воспроизводит список, содержащий 21 элемент – `['MSB',\n", + "'MSG', ..., 'FLW']`. Тот же самый список можно создать парой строк,\n", + "если воспользоваться генераторами списков:" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "codes = [s + z + c for s in \"MF\" for z in \"SMLX\" for c in \"BGW\"\n", + " if not (s == \"F\" and z == \"X\")]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Здесь каждый элемент списка воспроизводится выражением `s + z + c`.\n", + "Кроме того, в генераторе списков несколько иначе построена логика\n", + "обхода нежелательной комбинации пол/размер – проверка выполняется в\n", + "самом внутреннем цикле, тогда как в версии с циклами `for ... in` эта\n", + "проверка выполняется в среднем цикле. Любой генератор списков можно\n", + "переписать, используя один или более циклов `for ... in`. \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "# Множества\n", + "
\n", + "\n", + "Тип `set` – это разновидность коллекций, которая поддерживает оператор\n", + "проверки на вхождение `in`, функцию `len()` и относится к разряду\n", + "итерируемых объектов. Кроме того, множества предоставляют метод \n", + "`set.isdisjoint()` и поддерживают операторы сравнения и битовые\n", + "операторы (которые в контексте множеств используются для получения \n", + "объединения, пересечения и т. д.). В языке Python имеется два\n", + "встроенных типа множеств: изменяемый тип `set` и неизменяемый\n", + "`frozenset`. При переборе элементов множества элементы могут следовать\n", + "в произвольном порядке. \n", + "\n", + "В состав множеств могут включаться только *хешируемые*\n", + "объекты. Хешируемые объекты – это объекты, имеющие специальный метод \n", + "`__hash__()`, на протяжении всего жизненного цикла объекта всегда\n", + "возвращающий одно и то же значение, которые могут участвовать в\n", + "операциях сравнения на равенство посредством специального метода \n", + "`__eq__()`. (Специальные методы – это методы, имена которых начинаются\n", + "и оканчиваются двумя символами подчеркивания).\n", + "\n", + "Все встроенные неизменяемые типы данных, такие как `float`,\n", + "`frozenset`, `int`, `str` и `tuple`, являются хешируемыми объектами и\n", + "могут добавляться во множества. Встроенные изменяемые типы данных,\n", + "такие как `dict`, `list` и `set`, не являются хешируемыми объектами,\n", + "так как значение хеша в каждом конкретном случае зависит от\n", + "содержащихся в объекте элементов, поэтому они не могут добавляться в\n", + "множества.\n", + "\n", + "Множества могут сравниваться между собой с использованием стандартных\n", + "операторов сравнения (`<`, `<=`, `==`, `!=`, `>=`, `>`). Обратите\n", + "внимание: операторы `==` и `!=` имеют обычный смысл, и сравнение\n", + "выполняется путем поэлементного сравнения (или рекурсивно при наличии\n", + "таких вложенных элементов, как кортежи и фиксированные множества\n", + "(`frozenset`)), но остальные операторы сравнения выполняют сравнение\n", + "подмножеств и надмножеств, как вскоре будет показано. \n", + "\n", + "## Тип `set`\n", + "
\n", + "\n", + "Тип `set` – это неупорядоченная коллекция из нуля или более ссылок на\n", + "объекты, указывающих на хешируемые объекты. Множества относятся к\n", + "категории изменяемых типов, поэтому легко можно добавлять и удалять их\n", + "элементы, но, так как они являются неупорядоченными коллекциями, к ним\n", + "не применимо понятие индекса и не применима операция извлечения\n", + "среза. На рис. [collections:sets:fig:1](#collections:sets:fig:1) иллюстрируется множество,\n", + "созданное следующим фрагментом программного кода:" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "S = {7, \"veil\", 0, -29, (\"x\", 11), \"sun\", frozenset({8, 4, 7}), 913}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "
\n", + "![Множество – это неупорядоченная коллекция уникальных элементов](fig-collections/set_1.png)\n", + "\n", + "\n", + "Тип данных `set` может вызываться как функция `set()` –\n", + "без аргументов она возвращает пустое множество; с аргументом типа\n", + "`set` возвращает поверхностную копию аргумента; в случае, если\n", + "аргумент имеет другой тип, выполняется попытка преобразовать его в\n", + "объект типа `set`. Эта функция принимает не более одного\n", + "аргумента. Кроме того, непустые множества могут создаваться без\n", + "использования функции `set()`, а пустые множества могут создаваться\n", + "только с помощью функции `set()` – их нельзя создать с помощью пары\n", + "пустых скобок. Множество, состоящее из одного или более элементов,\n", + "может быть создано с помощью последовательности элементов, разделенных\n", + "запятыми, заключенной в фигурные скобки. Другой способ создания\n", + "множеств заключается в использовании генераторов множеств. Множества\n", + "всегда содержат уникальные элементы – добавление повторяющихся\n", + "элементов возможно, но не имеет смысла. Например, следующие три\n", + "множества являются эквивалентными: `set(\"apple\")`, `set(\"aple\")` и\n", + "`{'e', 'p', 'a', 'l'}`. Благодаря этой их особенности множества часто\n", + "используются для устранения повторяющихся значений. Например, если\n", + "предположить, что `x` – это список строк, то после выполнения\n", + "инструкции `x = list(set(x))` в списке останутся только уникальные\n", + "строки, причем располагаться они могут в произвольном порядке.\n", + "\n", + "\n", + "\n", + "
\n", + "![Стандартные операторы множеств](fig-collections/set_2.png)\n", + "\n", + "\n", + "Множества поддерживают встроенную функцию `len()` и быструю проверку\n", + "на вхождение с помощью операторов `in` и `not in`. Они также предоставляют\n", + "типичный набор операторов, как показано на рис. . \n", + "Полный перечень методов и операторов, применимых к множествам,\n", + "приводится в табл. [collections:sets:tbl:1](#collections:sets:tbl:1). Все методы семейства\n", + "«update» (`set.update()`, `set.intersection_update()` и т. д.) могут принимать в качестве\n", + "аргумента любые итерируемые объекты, но эквивалентные им\n", + "комбинированные операторы присваивания (`|=`, `&=` и т. д.) требуют, чтобы\n", + "оба операнда были множествами. \n", + "\n", + "\n", + "## Таблица 2 : Методы и операторы множеств
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Синтаксис Описание
s.add(x) Добавляет элементы x во множество s, если они отсутствуют в s
s.clear() Удаляет все элементы из множества s
s.difference(t)или s-t Возвращает новое множество включающее элементы множества s, которые отсутствуют в множестве t
s.difference_update(t) или s-=t Удаляет из множества s все элементы, присутствующие в множестве t
s.discard(x) Удаляет элемент x из множества s, если он присутствует в множестве s
s.intersection(t) или s & t Возвращает новое множество, включающее элементы, присутствующие одновременно в множествах s и t
s.intersection_update(t) или s &= t Оставляет во множестве s пересечение множеств s и t
s.isdisjoint(t) Возвращает True, если множества s и t не имеют общих элементов
s.issubset(t) или s <= t Возвращает True, если множество s эквивалентно множеству t или является его подмножеством; чтобы проверить, является ли множество s только подмножеством множества t, следует использовать проверку s < t
s.issuperset(t) или s >= t Возвращает True, если множество s эквивалентно множеству t или является его надмножеством; чтобы проверить, является ли множество s только надмножеством множества t, следует использовать проверку s > t
s.pop() Возвращает и удаляет случайный элемент множества s или возбуждает исключение KeyError, если s – это пустое множество
s.remove(x) Удаляет элемент x из множества s или возбуждает исключение KeyError, если элемент x отсутствует в множестве s
s.symmetric_difference(t) или s ^ t Возвращает новое множество, включающее все элементы, присутствующие в множествах s и t, за исключением элементов, присутствующих в обоих множествах одновременно
s.symmetric_difference_update(t) или s ^= t Возвращает в множестве s результат строгой дизъюнкции множеств s и t
s.union(t) или s | t Возвращает новое множество, включающее все элементы множества s и все элементы множества t, отсутствующие в множестве s
s.update(t) или s |= t Добавляет во множество s все элементы множества t, отсутствующие в множестве s
\n", + "\n", + "\n", + "### Генераторы множеств\n", + "\n", + "
\n", + "\n", + "В дополнение к возможности создавать множества с помощью функции\n", + "`set()` или литералов, существует возможность создавать множества с\n", + "помощью *генераторов множеств*. Генератор множества – это выражение и\n", + "цикл с необязательным условием, заключенные в фигурные скобки. Подобно\n", + "генераторам списков, генераторы множеств поддерживают две формы\n", + "записи:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```Python\n", + " {expression for item in iterable}\n", + " {expression for item in iterable if condition}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Мы могли бы использовать генераторы множеств для фильтрации\n", + "нежелательных элементов (когда порядок следования элементов не имеет\n", + "значения), как показано ниже:" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "html = {x for x in files if x.lower().endswith((\".htm\", \".html\"))}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Если предположить, что `files` – это список имен файлов, то данный\n", + "генератор множества создает множество `html`, в котором хранятся\n", + "только имена файлов с расширениями `.htm` и `.html`, независимо от\n", + "регистра символов.\n", + "\n", + "Как и в случае с генераторами списков, в генераторах множеств\n", + "используются итерируемые объеты, которые в свою очередь могут быть\n", + "генераторами множеств (или генераторами любого другого типа), что\n", + "позволяет создавать весьма замысловатые генераторы множеств.\n", + "\n", + "## Тип `frozenset`\n", + "
\n", + "\n", + "Фиксированное множество (`frozenset`) – это множество, которое после\n", + "создания невозможно изменить. Хотя при этом мы, конечно, можем\n", + "повторно связать переменную, которая ссылалась на фиксированное\n", + "множество, с чем-то другим. Фиксированные множества могут создаваться\n", + "только в результате обращения к имени типа `frozenset` как к\n", + "функции. При вызове `frozenset()` без аргументов возвращается пустое\n", + "фиксированное множество; с аргументом типа `frozenset` возвращается\n", + "поверхностная копия аргумента; если аргумент имеет другой тип,\n", + "выполняется попытка преобразовать его в объект типа `frozenset`. Эта\n", + "функция принимает не более одного аргумента.\n", + "\n", + "Поскольку фиксированные множества относятся к категории неизменяемых\n", + "объектов, они поддерживают только те методы и операторы, которые\n", + "воспроизводят результат, не оказывая воздействия на фиксированное\n", + "множество или на множества, к которым они применяются.\n", + "\n", + "Поскольку фиксированные множества относятся к категории неизменяемых\n", + "объектов, они поддерживают только те методы и операторы, которые\n", + "воспроизводят результат, не оказывая воздействия на фиксированное\n", + "множество или на множества, к которым они применяются. \n", + "В табл. [collections:sets:tbl:1](#collections:sets:tbl:1) перечислены все методы множеств из\n", + "которых фиксированными множествами поддерживаются: `frozenset.copy()`,\n", + "`frozenset.difference()` (`-`), `frozenset.intersection()` (`&`),\n", + "`frozenset.isdis-joint()`, `frozenset.issubset()` (`<=` и `<` для\n", + "выявления подмножеств), `frozenset.issuperset()` (`>=` и `>` для\n", + "выявления надмножеств), `frozenset.union()` (`|`) и\n", + "`frozenset.symmetric_difference()` (`^`).\n", + "\n", + "Если двухместный оператор применяется ко множеству и фиксированному\n", + "множеству, тип результата будет совпадать с типом операнда, стоящего\n", + "слева от оператора. То есть если предположить, что `f` – это\n", + "фиксированное множество, а `s` – это обычное множество, то выражение\n", + "`f & s` вернет объект типа frozenset, а выражение `s & f` – объект\n", + "типа `set`. В случае операторов `==` и `!=` порядок операндов не имеет\n", + "значения, и выражение `f == s` вернет `True`, только если оба\n", + "множества содержат одни и те же элементы.\n", + "\n", + "Другое следствие неизменности фиксированных множеств заключается в\n", + "том, что они соответствуют критерию хеширования, предъявляемому к\n", + "элементам множеств, и потому множества и фиксированные множества могут\n", + "содержать другие фиксированные множества.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "# Отображения\n", + "
\n", + "\n", + "Отображениями называются типы данных, поддерживающие оператор проверки\n", + "на вхождение (`in`), функцию `len()` и возможность обхода элементов в\n", + "цикле. Отображения – это коллекции пар элементов «ключ-значение»,\n", + "которые предоставляют методы доступа к элементам и их ключам и\n", + "значениям. При выполнении итераций порядок следования элементов\n", + "отображений может быть произвольным. В языке Python имеется два типа\n", + "отображений: встроенный тип `dict` и тип `collections.defaultdict`,\n", + "определяемый в стандартной библиотеке. Мы будем использовать термин\n", + "словарь для ссылки на любой из этих типов, когда различия между ними\n", + "не будут иметь никакого значения." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import collections.defaultdict" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "В качестве ключей словарей могут использоваться только хешируемые\n", + "объекты, поэтому в качестве ключей словаря такие неизменяемые типы,\n", + "как `float`, `frozenset`, `int`, `str` и `tuple`, использовать\n", + "допускается, а изменяемые типы, такие как `dict`, `list` и `set`, –\n", + "нет. С другой стороны, каждому ключу соответствует некоторое значение,\n", + "которое может быть ссылкой на объект любого типа, включая числа,\n", + "строки, списки, множества, словари, функции и т. д.\n", + "\n", + "Словари могут сравниваться с помощью стандартных операторов сравнения\n", + "(`<`, `<=`, `==`, `!=`, `>=`, `>`), при этом сравнивание производится\n", + "поэлементно (и рекурсивно, при наличии вложенных элементов, таких как\n", + "кортежи или словари в словарях). Пожалуй, единственными операторами\n", + "сравнения, применение которых к словарям имеет смысл, являются\n", + "операторы `==` и `!=`.\n", + "\n", + "## Словари\n", + "
\n", + "\n", + "Тип `dict` – это неупорядоченная коллекция из нуля или более пар\n", + "«ключ-значение», в которых в качестве ключей могут использоваться\n", + "ссылки на хешируемые объекты, а в качестве значений – ссылки на\n", + "объекты любого типа. Словари относятся к категории изменяемых типов,\n", + "поэтому легко можно добавлять и удалять их элементы, но так как они\n", + "являются неупорядоченными коллекциями, к ним не применимо понятие\n", + "индекса и не применима операция извлечения среза.\n", + "\n", + "Тип данных `dict` может вызываться как функция `dict()` – без\n", + "аргументов она возвращает пустой словарь; если в качестве аргумента\n", + "передается отображение, возвращается словарь, основанный на этом\n", + "отображении: например, с аргументом типа `dict` возвращается\n", + "поверхностная копия словаря. Существует возможность передавать в\n", + "качестве аргумента последовательности, если каждый элемент\n", + "последовательности в свою очередь является последовательностью из двух\n", + "объектов, первый из которых используется в качестве ключа, а второй –\n", + "в качестве значения. Как вариант, для создания словарей, в которых \n", + "ключи являются допустимыми идентификаторами языка Python, можно\n", + "использовать именованные аргументы; тогда имена аргументов будут\n", + "играть роль ключей, а значения аргументов – роль значений\n", + "ключей. Кроме того, словари могут создаваться с помощью фигурных\n", + "скобок – пустые скобки `{}` создадут пустой словарь. Непустые фигурные\n", + "скобки должны содержать один или более элементов, разделенных\n", + "запятыми, каждый из которых состоит из ключа, символа двоеточия и\n", + "значения. Еще один способ создания словарей заключается в\n", + "использовании генераторов словарей – эта тема будет рассматриваться\n", + "ниже, в соответствующем подразделе.\n", + "\n", + "Ниже приводятся несколько способов создания словарей – все они создают\n", + "один и тот же словарь:" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "d1 = dict({\"id\": 1948, \"name\": \"Washer\", \"size\": 3})\n", + "d2 = dict(id=1948, name=\"Washer\", size=3)\n", + "d3 = dict([(\"id\", 1948), (\"name\", \"Washer\"), (\"size\", 3)])\n", + "d4 = dict(zip((\"id\", \"name\", \"size\"), (1948, \"Washer\", 3)))\n", + "d5 = {\"id\": 1948, \"name\": \"Washer\", \"size\": 3}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "
\n", + "![Словарь – это неупорядоченная коллекция элементов (ключ, значение) с уникальными ключами](fig-collections/map_1.png)\n", + "\n", + "\n", + "На рис. [collections:maps:fig:1](#collections:maps:fig:1) демонстрируется словарь, созданный\n", + "следующим фрагментом программного кода:" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "d = {\"root\": 18, \"blue\": [75, \"R\", 2], 21: \"venus\", -14: None,\n", + " \"mars\": \"rover\", (4, 11): 18, 0: 45}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ключи словарей являются уникальными, поэтому если в словарь\n", + "добавляется пара «ключ-значение» с ключом, который уже присутствует в\n", + "словаре, в результате происходит замена значения существующего ключа\n", + "новым значением. Для доступа к отдельным элементам используются\n", + "квадратные скобки: например, выражение `d[\"root\"]` вернет `18`,\n", + "выражение `d[21]` вернет строку `\"venus\"`, а выражение `d[91]` \n", + "применительно к словарю, изображенному на\n", + "рис. [collections:maps:fig:1](#collections:maps:fig:1), возбудит исключение `KeyError`. \n", + "\n", + "Квадратные скобки могут также использоваться для добавления и удаления\n", + "элементов словаря. Чтобы добавить новый элемент, используется оператор\n", + "`=`, например, `d[\"X\"] = 59`. Для удаления элементов используется\n", + "инструкция `del`, например, инструкция `del d[\"mars\"]` удалит из \n", + "словаря элемент с ключом `\"mars\"` или возбудит исключение `KeyError`,\n", + "если элемент с указанным ключом отсутствует в словаре. Кроме того,\n", + "элементы могут удаляться (и возвращаться вызывающей программе)\n", + "методом `dict.pop()`.\n", + "\n", + "Словари поддерживают встроенную функцию `len()` и для ключей\n", + "поддерживают возможность быстрой проверки на вхождение с помощью\n", + "операторов `in` и `not in`. В табл. [collections:maps:tbl:1](#collections:maps:tbl:1)\n", + "перечислены все методы словарей.\n", + "\n", + "Так как словари содержат пары «ключ-значение», у нас может возникнуть\n", + "потребность обойти в цикле элементы словаря (ключ, значение) по\n", + "значениям или по ключам. Например, ниже приводятся два эквивалентных\n", + "способа обхода пар «ключ-значение»:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "3\n", + "8\n", + " \n", + "<\n", + "<\n", + "<\n", + "!\n", + "!\n", + "C\n", + "O\n", + "D\n", + "E\n", + "_\n", + "B\n", + "L\n", + "O\n", + "C\n", + "K\n", + " \n", + " \n", + "p\n", + "y\n", + "c\n", + "o\n", + "d" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for key, value in d.items():\n", + " print(key, value)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Таблица 3 : Методы словарей
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Синтаксис Описание
d.clear() Удаляет все элементы из словаря d
d.copy() Возвращает поверхностную копию словаря d
d.fromkeys(s, v) Возвращает словарь типа dict, ключами которого являются элементы последовательности s значениями либо None либо v, если аргумент v определен
d.get(k) Возвращает значение ключа k или None, если ключ k отсутствует в словаре
d.get(k, v) Возвращает значение ключа k или v, если ключ k отсутствует в словаре
d.items() Возвращает представление всех пар (ключ, значение) в словаре d
d.keys() Возвращает представление всех ключей словаря d
d.pop(k) Возвращает значение ключа k и удаляет из словаря элемент с ключом k или возбуждает исключение KeyError, если ключ k отсутствует в словаре
d.pop(k, v) Возвращает значение ключа k и удаляет из словаря элемент с ключом k или возвращает значение v, если ключ k отсутствует в словаре
d.popitem() Возвращает и удаляет произвольную пару (ключ, значение) из словаря d или возбуждает исключение KeyError, если словарь d пуст
d.setdefault(k, v) То же что и dict.get() за исключением того, что, если ключ k в словаре отсутствует, в словарь вставляется новый элемент с ключом k и со значением None или v, если аргумент v задан
d.update(a) Добавляет в словарь d пары (ключ, значение) из a, которые отсутствуют в словаре d а для каждого ключа который уже присутствует в словаре d выполняется замена соответствующим значением из a; a может быть словарем итерируемым объектом с парами (ключ значение) или именованными аргументами
d.values() Возвращает представление всех значений в словаре d
\n", + "\n", + "\n", + "\n", + "Обход значений в словаре выполняется похожим способом:" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for value in d.values():\n", + " print(value)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Для обхода ключей в словаре можно использовать метод `dict.keys()`\n", + "или просто интерпретировать словарь как итерируемый объект и вы-\n", + "полнить итерации по его ключам, как показано в следующих двух\n", + "фрагментах:" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for key in d:\n", + " print(key)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for key in d.keys():\n", + " print(key)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Если необходимо изменить значения в словаре, то можно выполнить\n", + "обход ключей словаря в цикле и изменить значения, используя оператор\n", + "квадратных скобок. Например, ниже показано, как можно было бы\n", + "увеличить все значения в словаре `d`, если предполагать, что все\n", + "значения являются числами:" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for key in d:\n", + " d[key] += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Методы `dict.items()`, `dict.keys()` и `dict.values()` возвращают\n", + "представления словарей. Представление словаря – это в действительности\n", + "итерируемый объект, доступный только для чтения и хранящий элементы,\n", + "ключи или значения словаря в зависимости от того, какое представление\n", + "было запрошено.\n", + "\n", + "### Генераторы словарей\n", + "\n", + "
\n", + "\n", + "*Генератор словарей* – это выражение и цикл с необязательным условием,\n", + "заключенное в фигурные скобки, очень напоминающее генератор\n", + "множеств. Подобно генераторам списков и множеств, генераторы словарей\n", + "поддерживают две формы записи:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```Python\n", + " {keyexpression: valueexpression for key, value in iterable}\n", + " {keyexpression: valueexpression for key, value in iterable if condition}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ниже показано, как можно использовать генератор словарей для создания\n", + "словаря, в котором каждый ключ является именем файла в текущем\n", + "каталоге, а каждое значение – это размер файла в байтах:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```Python\n", + " file_sizes = {name: os.path.getsize(name) for name in os.listdir(\".\")}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Функция `os.listdir()` из модуля os («operating system» – операционная\n", + "система) возвращает список файлов и каталогов в указанном каталоге, но\n", + "при этом в список никогда не включаются специальные имена каталогов\n", + "«.» или «..». Функция os.path.getsize() возвращает размер заданного\n", + "файла в байтах. Чтобы отфильтровать каталоги и другие элементы списка,\n", + "не являющиеся файлами, можно добавить дополнительное условие:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```Python\n", + " file_sizes = {name: os.path.getsize(name) for name in os.listdir(\".\")\n", + " \t if os.path.isfile(name)}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Функция `os.path.isfile()` из модуля `os.path` возвращает `True`, если\n", + "указанный путь соответствует файлу, и `False` – в противном случае, то\n", + "есть для каталогов, ссылок и тому подобного.\n", + "\n", + "Генераторы словарей могут также использоваться для создания инвер-\n", + "тированных словарей. Например, пусть имеется словарь `d`, тогда мы\n", + "можем создать новый словарь, ключами которого будут значения словаря\n", + "`d`, а значениями – ключи словаря `d`:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```Python\n", + " inverted_d = {v: k for k, v in d.items()}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Полученный словарь можно инвертировать обратно и получить\n", + "первоначальный словарь – при условии, что все значения в\n", + "первоначальном словаре были уникальными, однако инверсия будет терпеть\n", + "неудачу, с возбуждением исключения `TypeError`, если какое-либо\n", + "значение окажется не хешируемым.\n", + "\n", + "\n", + "## Словари со значениями по умолчанию\n", + "
\n", + "\n", + "Словари со значениями по умолчанию – это обычные словари, они\n", + "поддерживают те же самые методы и операторы, что и обычные\n", + "словари. Единственное, что отличает такие словари от обычных словарей,\n", + "– это способ обработки отсутствующих ключей, но во всех остальных\n", + "отношениях они ничем не отличаются друг от друга. \n", + "\n", + "При обращении к несуществующему («отсутствующему») ключу слова-\n", + "ря возбуждается исключение `KeyError`. Это очень удобно, так как\n", + "нередко для нас бывает желательно знать об отсутствии ключа, который,\n", + "согласно нашим предположениям, может присутствовать. Но в некоторых\n", + "случаях бывает необходимо, чтобы в словаре присутствовали все ключи,\n", + "которые мы используем, даже если это означает, что элемент с заданным\n", + "ключом добавляется в словарь в момент первого обращения к нему.\n", + "\n", + "Например, допустим, что имеется словарь `d`, который не имеет элемента\n", + "с ключом m, тогда выражение `x = d[m]` возбудит исключение\n", + "`KeyError`. Если `d` – это словарь со значениями по умолчанию,\n", + "созданный соответствующим способом, а элемент с ключом m принадлежит\n", + "такому словарю, то при обращении к нему будет возвращено\n", + "соответствующее значение, как и в случае с обычным словарем. Но если в\n", + "словаре со значениями по умолчанию отсутствует ключ m, то будет создан\n", + "новый элемент словаря с ключом m и со значением по умолчанию, и будет\n", + "возвращено значение этого, вновь созданного элемента. \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "# Обход в цикле и копирование коллекций\n", + "
\n", + "\n", + "После того как будет создана коллекция элементов данных, вполне\n", + "естественно возникает желание обойти все элементы, содержащиеся в\n", + "ней. Еще одна часто выполняемая операция – копирование коллекций. Из-за\n", + "того, что в языке Python повсеместно используются ссылки на объекты\n", + "(ради повышения эффективности), существуют некоторые особенности,\n", + "связанные с копированием.\n", + "\n", + "В этом разделе сначала мы рассмотрим итераторы языка Python, а затем\n", + "принципы копирования коллекций.\n", + "\n", + "## Итераторы, функции и операторы для работы с итерируемыми объектами\n", + "
\n", + "\n", + "*Итерируемый* тип данных – это такой тип, который может возвращать\n", + "свои элементы по одному. Любой объект, имеющий метод `__iter__()`, или\n", + "любая последовательность (то есть объект, имеющий метод\n", + "`__getitem__()`, принимающий целочисленный аргумент со значением от\n", + "`0` и выше), является итерируемым и может предоставлять\n", + "итератор. Итератор – это объект, имеющий метод `__next__()`, который\n", + "при каждом вызове возвращает очередной элемент и возбуждает исключение\n", + "`StopIteration` после исчерпания всех элементов. В\n", + "табл. [collections:iterandcopy:iterator:tbl:1](#collections:iterandcopy:iterator:tbl:1) перечислены\n", + "операторы и функции, которые могут применяться к итерируемым\n", + "объектам. \n", + "\n", + "\n", + "## Таблица 4 : Общие функции и операторы для работы с итерируемыми объектами
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Синтаксис Описание
s + t Возвращает конкатенацию последовательностей s и t
s * n Возвращает конкатенацию из int n последовательностей s
x in i Возвращает True, если элемент x присутствует в итерируемом объекте i, обратная проверка выполняется с помощью оператора not in
all(i) Возвращает True, если все элементы итерируемого объекта i в логическом контексте оцениваются как значение True
any(i) Возвращает True, если хотя бы один элемент итерируемого объекта i в логическом контексте оценивается как значение True
enumerate (i,start) Обычно используется в циклах for ... in, чтобы получить последовательность кортежей (index, item), где значения индексов начинают отсчитывать от 0 или от значения start
len(x) Возвращает «длину» объекта x. Если x – коллекция, то возвращаемое число представляет количество элементов. Если x – строка, то возвращаемое число представляет количество символов
max(i, key) Возвращает наибольший элемент в итерируемом объекте i или элемент с наибольшим значением key(item), если функция key определена
min(i, key) Возвращает наименьший элемент в итерируемом объекте i или элемент с наименьшим значением key(item), если функция key определена
range(start, stop, step) Возвращает целочисленный итератор. С одним аргументом (stop) итератор представляет последовательность целых чисел от 0 до stop-1, с двумя аргументами (start, stop) – последовательность целых чисел от start до stop-1, с тремя аргументами – последовательность целых чисел от start до stop-1 c шагом step
reversed(i) Возвращает итератор, который будет возвращать элементы итератора i в обратном порядке
sorted(i, key, reverse) Возвращает список элементов итератора i в отсортированном порядке. Аргумент key используется для выполнения сортировки DSU (Decorate, Sort, Undecorate – декорирование, сортировка, обратное декорирование). Если аргумент reverse имеет значение True, сортировка выполняется в обратном порядке
sum(i, start) Возвращает сумму элементов итерируемого объекта i, плюс ар гумент start (значение которого по умолчанию равно 0). Объект i не должен содержать строк
zip(i1, ..., iN) Возвращает итератор кортежей, используя итераторы от i1 до iN
\n", + "\n", + "\n", + "Порядок, в котором возвращаются элементы, зависит от итерируемого\n", + "объекта. В случае списков и кортежей элементы обычно возвращаются\n", + "в предопределенном порядке, начиная с первого элемента (находящегося в\n", + "позиции с индексом `0`), но другие итераторы возвращают элементы в\n", + "произвольном порядке – например, итераторы словарей и множеств.\n", + "\n", + "Встроенная функция `iter()` используется двумя совершенно различными\n", + "способами. Применяемая к коллекции или к последовательности, она\n", + "возвращает итератор для заданного объекта или возбуждает исключение\n", + "`TypeError`, если объект не является итерируемым. Такой способ часто\n", + "используется при работе с нестандартными типами коллекций \n", + "и крайне редко – в других контекстах. Во втором варианте использования\n", + "функции `iter()` ей передается вызываемый объект (функция или метод) и\n", + "специальное значение. В этом случае полученная функция или метод\n", + "вызывается на каждой итерации, а значение этой функции, если оно не\n", + "равно специальному значению, возвращается вызывающей программе; в\n", + "противном случае возбуждается исключение `StopIteration`.\n", + "\n", + "Когда в программе используется цикл `for item in iterable`,\n", + "интерпретатор Python вызывает функцию `iter(iterable)`, чтобы получить\n", + "итератор. После этого на каждой итерации вызывается метод `__next__()`\n", + "итератора, чтобы получить очередной элемент, а когда возбуждается\n", + "исключение `StopIteration`, оно перехватывается и цикл завершается.\n", + "Другой способ получить очередной элемент итератора состоит в том,\n", + "чтобы вызвать встроенную функцию `next()`. Ниже приводятся два\n", + "эквивалентных фрагмента программного кода (оба они вычисляют\n", + "произведение элементов списка), в одном из них используется цикл\n", + "`for ... in`, а во втором явно используется итератор:" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "product = 1\n", + "for i in [1, 2, 4, 8]:\n", + " product *= i\n", + "print(product)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "product = 1\n", + "i = iter([1, 2, 4, 8])\n", + "while True:\n", + " try:\n", + " product *= next(i)\n", + " except StopIteration:\n", + " break\n", + "print(product)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Любой (конечный) итерируемый объект `i` может быть преобразован\n", + "в кортеж вызовом функции `tuple(i)` или в список – вызовом функции\n", + "`list(i)`.\n", + "\n", + "## Копирование коллекций\n", + "
\n", + "\n", + "Поскольку в языке Python повсюду используются ссылки на объекты, когда\n", + "выполняется оператор присваивания (`=`), никакого копирования данных\n", + "на самом деле не происходит. Если справа от оператора находится\n", + "литерал, например, строка или число, в операнд слева записывается\n", + "ссылка, которая указывает на объект в памяти, хранящий значение\n", + "литерала. Если справа находится ссылка на объект, в левый операнд\n", + "записывается ссылка, указывающая на тот же самый объект, на который\n", + "ссылается правый операнд. Вследствие этого операция присваивания\n", + "обладает чрезвычайно высокой скоростью выполнения. \n", + "\n", + "Когда выполняется присваивание крупной коллекции, такой как\n", + "длинный список, экономия времени становится более чем очевидной.\n", + "Например:" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "songs = [\"Because\", \"Boys\", \"Carol\"]\n", + "beatles = songs\n", + "beatles, songs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Здесь была создана новая ссылка на объект (`beatles`), и обе ссылки\n", + "указывают на один и тот же список – никакого копирования данных не\n", + "производилось. \n", + "\n", + "Поскольку списки относятся к категории изменяемых объектов, мы\n", + "можем вносить в них изменения. Например:" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "beatles[2] = \"Cayenne\"\n", + "beatles, songs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Изменения были внесены с использованием переменной `beatles`, но это\n", + "всего лишь ссылка, указывающая на тот же самый объект, что и ссылка\n", + "songs. Поэтому любые изменения, произведенные с использованием одной\n", + "ссылки, можно наблюдать с использованием другой ссылки. \n", + "Часто это именно то, что нам требуется, поскольку копирование крупных\n", + "коллекций может оказаться дорогостоящей операцией. Кроме того, это\n", + "также означает, что имеется возможность передавать списки или другие\n", + "изменяемые коллекции в виде аргументов функций, изменять эти коллекции\n", + "в функциях и пребывать в уверенности, что изменения будут доступны\n", + "после того, как функция вернет управление вызывающей программе. \n", + "\n", + "Однако в некоторых ситуациях действительно бывает необходимо создать\n", + "отдельную копию коллекции (то есть создать другой изменяемый\n", + "объект). В случае последовательностей, когда выполняется оператор\n", + "извлечения среза, например, `songs[:2]`, полученный срез – это всегда \n", + "независимая копия элементов. Поэтому скопировать последовательность\n", + "целиком можно следующим способом:" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "songs = [\"Because\", \"Boys\", \"Carol\"]\n", + "beatles = songs[:]\n", + "beatles[2] = \"Cayenne\"\n", + "beatles, songs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "В случае словарей и множеств копирование можно выполнить с помощью\n", + "методов `dict.copy()` и `set.copy()`. Кроме того, в модуле copy\n", + "имеется функция copy.copy(), которая возвращает копию заданного\n", + "объекта. Другой способ копирования встроенных типов коллекций\n", + "заключается в использовании имени типа как функции, которой в качестве\n", + "аргумента передается копируемая коллекция. Например:" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "copy_of_dict_d = dict(d)\n", + "copy_of_list_L = list(L)\n", + "copy_of_set_s = set(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Обратите внимание, что все эти приемы копирования\n", + "создают *поверхностные копии*, то есть копируются только ссылки на\n", + "объекты, но не сами объекты. Для неизменяемых типов данных, таких как числа\n", + "и строки, это равносильно копированию (за исключением более высокой\n", + "эффективности), но для изменяемых типов данных, таких как вложенные\n", + "коллекции, это означает, что ссылки в оригинальной коллекции и в копии\n", + "будут указывать на одни и те же объекты. Эту особенность иллюстрирует\n", + "следующий пример:" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = [53, 68, [\"A\", \"B\", \"C\"]]\n", + "y = x[:] # поверхностное копирование\n", + "x, y" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "y[1] = 40\n", + "x[2][0] = 'Q'\n", + "x, y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Когда выполняется поверхностное копирование списка `x`, копируется\n", + "ссылка на вложенный список `[\"A\", \"B\", \"C\"]`. Это означает, что третий\n", + "элемент в обоих списках, `x` и `y`, ссылается на один и тот же список,\n", + "поэтому любые изменения, произведенные во вложенном списке, можно\n", + "наблюдать с помощью любой из ссылок, `x` или `y`. Если действительно\n", + "необходимо создать абсолютно независимую копию коллекции с\n", + "произвольной глубиной вложенности, необходимо выполнить глубокое \n", + "копирование:" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import copy\n", + "x = [53, 68, [\"A\", \"B\", \"C\"]]\n", + "y = copy.deepcopy(x)\n", + "y[1] = 40\n", + "x[2][0] = 'Q'\n", + "x, y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Здесь списки `x` и `y`, а также элементы, которые они содержат,\n", + "полностью независимы. \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/datatype.ipynb b/datatype.ipynb index b3fff2f..b5c5907 100644 --- a/datatype.ipynb +++ b/datatype.ipynb @@ -10,15 +10,13 @@ " \n", "**С.В. Лемешевский** (email: `sergey.lemeshevsky@gmail.com`), Институт математики НАН Беларуси\n", "\n", - "Date: **Feb 24, 2020**\n", + "Date: **Feb 27, 2020**\n", "\n", "\n", "\n", "\n", "\n", "\n", - "\n", - "\n", "Здесь разберем как Python работает с переменными и определим, какие\n", "типы данных можно использовать в рамках этого языка. Подробно рассмотрим модель\n", "данных Python, а также механизмы создания и изменения значения\n", @@ -1514,7 +1512,7 @@ "Как показано в примере, мы можем также использовать комбинированный\n", "оператор присваивания с дублированием. \n", "\n", - "# Форматирование строк с помощью метода `str.format()`\n", + "## Форматирование строк с помощью метода `str.format()`\n", "
\n", "\n", "Метод `str.format()` представляет собой очень мощное и гибкое средство\n", @@ -1608,6 +1606,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "В следующем разделе мы рассмотрим применение функции `str.format()`.\n", + "\n", "\n", "\n", "\n", @@ -1615,8 +1615,195 @@ "# Примеры\n", "
\n", "\n", + "## Печать символов Юникода\n", + "
\n", "\n", + "Рассмотрим небольшой, но достаточно поучительный пример использования\n", + "метода `str.format()`, в котором мы увидим применение спецификаторов\n", + "формата в реальном контексте. Программа, состоящая всего из 25 строк\n", + "выполняемого кода, находится в файле\n", + "[print_unicode.py](src-datatype/print_unicode.py). Она импортирует\n", + "два модуля, `sys` и `unicodedata` и определяет одну функцию –\n", + "`print_unicode_table()`. Рассмотрение примера мы начнем\n", + "с запуска программы, чтобы увидеть, что она делает; затем мы\n", + "рассмотрим программный код в конце программы, где выполняется вся\n", + "фактическая работа; и в заключение рассмотрим функцию, определяемую в\n", + "программе." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%run src-datatype/print_unnicode.py Spoked" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "При запуске без аргументов программа выводит таблицу всех символов\n", + "Юникода, начиная с пробела и до символа с наибольшим возможным\n", + "кодом. При запуске с аргументом, как показано в примере, выводятся \n", + "только те строки таблицы, где в названии символов Юникода содержится\n", + "значение строки-аргумента, переведенной в нижний регистр.\n", "\n", + "Разберем исходный код программы:" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Start main script\n", + "word = None\n", + "\n", + "if len(sys.argv) > 1:\n", + " if sys.argv[1] in (\"-h\", \"--help\"):\n", + " print(\"usage: {0} [string]\".format(sys.argv[0]))\n", + " word = 0\n", + " else:\n", + " word = sys.argv[1].lower()\n", + "\n", + "if word != 0:\n", + " print_unicode_table(word)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "После инструкций импортирования и определения функции\n", + "`print_unicode_table()` выполнение достигает программного кода,\n", + "показанного выше. Сначала предположим, что пользователь не указал в\n", + "командной строке искомое слово. Если аргумент командной строки\n", + "присутствует и это `-h` или `--help`, программа выводит информацию о\n", + "порядке использования и устанавливает флаг `word` в значение `0`, указывая\n", + "тем самым, что работа завершена. В противном случае в переменную `word`\n", + "записывается копия аргумента, введенного пользователем, с\n", + "преобразованием всех символов в нижний регистр. Если значение `word` не\n", + "равно `0`, программа выводит таблицу.\n", + "\n", + "При выводе информации о порядке использования применяется спецификатор\n", + "формата, который представляет собой простое имя формата, в данном\n", + "случае – порядковый номер позиционного аргумента. Мы могли бы записать\n", + "эту строку, как показано ниже:" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"usage: {0[0]} [string]\".format(sys.argv))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "При таком подходе первый символ `0` соответствует порядковому номеру\n", + "позиционного аргумента, а `[0]` — это индекс элемента внутри\n", + "аргумента, и такой прием сработает, потому что `sys.argv` является\n", + "списком." + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def print_unicode_table(word):\n", + " print(\"decimal hex chr {0:^40}\".format(\"name\"))\n", + " print(\"------- ----- --- {0:-<40}\".format(\"\"))\n", + "\n", + " code = ord(\" \")\n", + " end = sys.maxunicode\n", + "\n", + " while code < end:\n", + " c = chr(code)\n", + " name = unicodedata.name(c, \"*** unknown ***\")\n", + " if word is None or word in name.lower():\n", + " print(\"{0:7} {0:5X} {0:^3c} {1}\".format(code, name.title()))\n", + " code += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Первый вызов `str.format()` выводит текст `\"name\"`, отцентрированный в\n", + "поле вывода, шириной 40 символов, а второй вызов выводит пустую строку\n", + "в поле шириной 40 символов, используя символ `-` в качестве\n", + "символа-заполнителя, с выравниванием по левому краю. \n", + "\n", + "Как вариант, вторую строку функции можно было записать, как показано ниже:" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"------- ----- --- {0}\".format(\"-\" * 40))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Здесь мы использовали оператор дублирования строки (`*`), чтобы\n", + "создать необходимую строку, и просто вставили ее в строку формата.\n", + "\n", + "Текущий код символа Юникода сохраняется в переменной `code`, которая\n", + "инициализируется кодом пробела (`0x20`). В переменную end записывается\n", + "максимально возможный код символа Юникода, который может принимать\n", + "разные значения в зависимости от того, какая из кодировок\n", + "использовалась при компиляции Python.\n", + "\n", + "Внутри цикла `while` с помощью функции `chr()` мы получаем символ\n", + "Юникода, соответствующий числовому коду. Функция `unicodedata.name()`\n", + "возвращает название заданного символа Юникода, во втором\n", + "необязательном аргументе передается имя, которое будет использовано в\n", + "случае, когда имя символа не определено. \n", + "\n", + "Если пользователь не указывает аргумент командной строки (`word is None`)\n", + "или аргумент был указан и он входит в состав копии имени символа\n", + "Юникода, в которой все символы приведены к нижнему регистру, то\n", + "выводится соответствующая строка таблицы. \n", + "\n", + "Мы передаем переменную `code` методу `str.format()` один раз, но в\n", + "строке формата она используется трижды. Первый раз – при выводе\n", + "значения `code` как целого числа в поле с шириной 7 символов (по\n", + "умолчанию в качестве символа-заполнителя используется пробел, поэтому\n", + "нет необходимости явно указывать его). Второй раз – при выводе\n", + "значения `code` как целого числа в шестнадцатеричном формате символами\n", + "верхнего регистра в поле шириной 5 символов. И третий раз – при выводе \n", + "символа Юникода, соответствующего значению code, с помощью\n", + "спецификатора формата `c`, отцентрированного в поле с минимальной \n", + "шириной 3 символа. Обратите внимание, что нам не потребовалось\n", + "указывать тип `d` в первом спецификаторе формата, потому что он\n", + "подразумевается по умолчанию для целых чисел. Второй аргумент –\n", + "это имя символа Юникода, которое выводится с помощью метода\n", + "`str.title()`, в результате которого первый символ каждого слова\n", + "преобразуется к верхнему регистру, а остальные символы – к нижнему. \n", "\n", "\n", "## `quadratic.py`\n", @@ -1658,17 +1845,701 @@ "С коэффициентами $1.5$, $-3$ и $6$ программа выведет (некоторые цифры\n", "обрезаны):\n", "\n", + "Теперь обратимся к программному коду, который начинается тремя инструкциями `import`:\n", + "\n", + "Нам необходимы обе математические библиотеки для работы с числами типа\n", + "`float` и `complex`, так как функции, вычисляющие квадратный \n", + "корень из вещественных и комплексных чисел, отличаются. Модуль\n", + "`sys` нам необходим, так как в нем определена константа\n", + "`sys.float_info.epsilon`, которая потребуется нам для сравнения\n", + "вещественных чисел со значением `0`.\n", + "\n", + "Нам также необходима функция, которая будет получать от пользова-\n", + "теля число с плавающей точкой:" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Start get_float\n", + "def get_float(msg, allow_zero):\n", + " x = None\n", + " while x is None:\n", + " try:\n", + " x = float(input(msg))\n", + " if not allow_zero and abs(x) < sys.float_info.epsilon:\n", + " print(\"zero is not allowed\")\n", + " x = None\n", + "\n", + " except ValueError as err:\n", + " print(err)\n", + " return x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Эта функция выполняет цикл, пока пользователь не введет допустимое\n", + "число с плавающей точкой (например, `0.5`, `-9`, `21`, `4.92`), и допускает\n", + "ввод значения `0`, только если аргумент `allow_zero` имеет значение `True`.\n", + "Вслед за определением функции `get_float()` выполняется оставшаяся\n", + "часть программного кода. Мы разделим его на три части и начнем со\n", + "взаимодействия с пользователем:" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Start 1st block\n", + "print(\"ax\\N{SUPERSCRIPT TWO} + bx + c = 0\")\n", + "a = get_float(\"enter a: \", False)\n", + "b = get_float(\"enter b: \", False)\n", + "c = get_float(\"enter c: \", False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Благодаря функции `get_float()` получить значения коэффициентов `a`,\n", + "`b` и `c` оказалось очень просто. Второй аргумент функции сообщает, когда\n", + "значение `0` является допустимым." + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Start 2d block\n", + "x1 = None\n", + "x2 = None\n", + "discriminant = (b ** 2) - (4 * a * c)\n", + "if discriminant == 0:\n", + " x1 = -(b / (2 * a))\n", + "else:\n", + " if discriminant > 0:\n", + " root = math.sqrt(discriminant)\n", + " else: # discriminant < 0\n", + " root = cmath.sqrt(discriminant)\n", + " x1 = (-b + root) / (2 * a)\n", + " x2 = (-b - root) / (2 * a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Программный код выглядит несколько иначе, чем формула, потому\n", + "что мы начали вычисления с определения значения дискриминанта.\n", + "Если дискриминант равен `0`, мы знаем, что уравнение имеет\n", + "единственное действительное решение и можно сразу же вычислить его. В\n", + "противном случае мы вычисляем действительный или комплексный\n", + "квадратный корень из дискриминанта и находим два корня уравнения." + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Start 3d block\n", + "equation = (\"{0}x\\N{SUPERSCRIPT TWO} + {1}x + {2} = 0\"\n", + " \" \\N{RIGHTWARDS ARROW} x = {3}\").format(a, b, c, x1)\n", + "if x2 is not None:\n", + " equation += \" or x = {0}\".format(x2)\n", + "print(equation)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Мы не использовали сколько-нибудь сложного форматирования, поскольку\n", + "форматирование, используемое по умолчанию для чисел с плавающей точкой\n", + "в языке Python, прекрасно подходит для этого примера, но мы\n", + "использовали некоторые имена Юникода для вывода пары специальных\n", + "символов.\n", + "\n", + "## `csv2html.py`\n", + "
\n", + "\n", + "Часто бывает необходимо представить данные в формате HTML. В этом\n", + "подразделе мы разработаем программу, которая читает данные из\n", + "файла в простом формате CSV (Comma Separated Value – значения,\n", + "разделенные запятыми) и выводит таблицу HTML, содержащую эти\n", + "данные. В составе Python присутствует мощный и сложный модуль\n", + "для работы с форматом CSV и похожими на него – модуль csv, но здесь\n", + "мы будем выполнять всю обработку вручную.\n", + "\n", + "В формате CSV каждая запись располагается на одной строке, а поля\n", + "внутри записи отделяются друг от друга запятыми. Каждое поле может\n", + "быть либо строкой, либо числом. Строки должны окружаться апострофами\n", + "или кавычками, а числа не должны окружаться кавычками, если они не\n", + "содержат запятые. Внутри строк допускается присутствие запятых, и они\n", + "не должны интерпретироваться как разделители полей. Мы будем исходить\n", + "из предположения, что первая запись в файле содержит имена полей. На\n", + "выходе будет воспроизводиться таблица в формате HTML с выравниванием\n", + "текста по левому краю (по умолчанию для HTML) и с выравниванием чисел\n", + "по правому краю, по одной строке на запись и по одной ячейке на поле.\n", + "\n", + "Ниже приводится маленький фрагмент файла с данными:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \"COUNTRY\",2000,2001,2002,2003,2004\n", + " \"ANTIGUA AND BARBUDA\",0,0,0,0,0\n", + " \"ARGENTINA\",37,35,33,36,39\n", + " \"BAHAMAS, THE\",1,1,1,1,1\n", + " \"BAHRAIN\",5,6,6,6,6\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Предположим, что данные находятся в файле\n", + "\"sample.csv\": \"src-datatype/sample.csv\" и выполнена комадна" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " Terminal> python csv2html.py < sample.csv > sample.html\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "тогда файл [sample.html](src-datatype/sample.html) должен содержать\n", + "примерно следующее:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\"Country\"20002001200220032004
\"Antigua and Barbuda\"00000
\"Argentina\"3735333639
\"Bahamas, The\"11111
\"Bahrain\"56666
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "На рис. показано, как выглядит полученная таблица в веб-броузере.\n", + "\n", + "\n", + "\n", + "
\n", + "![Таблица, произведенная программой csv2html.py, в броузере](fig-datatype/example_1.png)\n", + "\n", + "\n", + "Теперь, когда мы увидели, как используется программа и что она делает,\n", + "можно приступать к изучению программного кода.\n", + "\n", + "Последняя инструкция в программе – это простой вызов функции:" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "main()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Хотя в языке Python не требуется явно указывать точку входа в\n", + "программу, как в некоторых других языках программирования, тем не\n", + "менее является распространенной практикой создание в программе на\n", + "языке Python функции с именем `main()`, которая вызывается для\n", + "выполнения обработки. Поскольку функция не может вызываться до того,\n", + "как она будет определена, мы должны вставлять вызов `main()` только\n", + "после того, как данная функция будет определена. Порядок следования\n", + "функций в файле (то есть порядок, в котором они создаются) не \n", + "имеет значения.\n", + "\n", + "В программе `csv2html.py` первой вызываемой функцией является функция\n", + "`main()`, которая в свою очередь вызывает функции `print_start()` и\n", + "`print_line()`. Функция `print_line()` вызывает функции\n", + "`extract_fields()` и `escape_html()`.\n", + "\n", + "Когда интерпретатор Python читает файл, он начинает делать это с\n", + "самого начала. Поэтому сначала будет выполнен импорт (если он есть),\n", + "затем будет создана функция `main()`, а затем будут созданы остальные\n", + "функции – в том порядке, в каком они следуют в файле. Когда\n", + "интерпретатор, наконец, достигнет вызова `main()` в конце файла, все\n", + "функции, которые вызываются функцией `main()` (и все функции, которые\n", + "вызываются этими функциями), будут определены. Выполнение обработки,\n", + "как и следовало ожидать, начинается в точке вызова функции `main()`.\n", + "\n", + "Рассмотрим все функции по порядку, начиная с функции `main()`." + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def main():\n", + " maxwidth = 100\n", + " print_start()\n", + " count = 0\n", + " while True:\n", + " try:\n", + " line = input()\n", + " if count == 0:\n", + " color = \"lightgreen\"\n", + " elif count % 2:\n", + " color = \"white\"\n", + " else:\n", + " color = \"lightyellow\"\n", + " print_line(line, color, maxwidth)\n", + " count += 1\n", + " except EOFError:\n", + " break\n", + " print_end()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Переменная `maxwidth` используется для хранения числа символов в\n", + "ячейке. Если поле больше, чем это число, часть строки отсекается и на\n", + "место отброшенного текста добавляется многоточие. Программный код\n", + "функций `print_start()`, `print_line()` и `print_end()` будет приведен\n", + "чуть ниже. Цикл while выполняет обход всех входных строк – это могут\n", + "быть строки, вводимые пользователем с клавиатуры, но мы предполагаем,\n", + "что данные будут перенаправлены из файла. Далее выбирается цвет фона и\n", + "вызывается функция `print_line()`, которая выводит строку в виде строки\n", + "таблицы в формате HTML." + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def print_start():\n", + " print(\"\")\n", + "\n", + "def print_end():\n", + " print(\"
\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Мы могли бы не создавать эти две функции и просто вставить\n", + "соответствующие вызовы `print()` в функцию `main()`. Но мы предпочитаем\n", + "выделять логику, так как это делает реализацию более гибкой, хотя\n", + "в этом маленьком примере гибкость не имеет большого значения." + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def print_line(line, color, maxwidth):\n", + " print(\"\".format(color))\n", + " fields = extract_fields(line)\n", + " for field in fields:\n", + " if not field:\n", + " print(\"\")\n", + " else:\n", + " number = field.replace(\",\", \"\")\n", + " try:\n", + " x = float(number)\n", + " print(\"{0:d}\".format(round(x)))\n", + " except ValueError:\n", + " field = field.title()\n", + " field = field.replace(\" And \", \" and \")\n", + " field = escape_html(field)\n", + " if len(field) <= maxwidth:\n", + " print(\"{0}\".format(field))\n", + " else:\n", + " print(\"{0:.{1}} ...\".format(field, maxwidth))\n", + " print(\"\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Мы не можем использовать метод `str.split(\",\")` для разбиения каждой\n", + "строки на поля, потому что запятые могут находиться внутри строк в\n", + "кавычках. Поэтому мы возложили эту обязанность на функцию\n", + "`extract_fields()`. Получив список строк полей (в виде строк без\n", + "окружающих их кавычек), мы выполняем обход списка и создаем для \n", + "каждого поля ячейку таблицы.\n", + "\n", + "Если поле пустое, мы выводим пустую ячейку. Если поле было заключено в\n", + "кавычки, это может быть строка или число в кавычках, содержащее\n", + "символы запятой, например `\"1,566\"`. Учитывая такую возможность, мы\n", + "создаем копию поля без запятых и пытаемся преобразовать ее в число\n", + "типа `float`. Если преобразование удалось, мы определяем выравнивание\n", + "в ячейке по правому краю, а значение поля округляется до ближайшего\n", + "целого, которое и выводится. Если преобразование не удалось,\n", + "следовательно, поле содержит строку. В этом случае мы с помощью метода\n", + "`str.title()` изменяем регистр символов и замещаем слово «And» на слово\n", + "«and», устраняя побочный эффект действия метода \n", + "`str.title()`. Затем выполняется экранирование специальных символов\n", + "HTML и выводится либо поле целиком, либо первые `maxwidth` символов\n", + "с добавлением многоточия. Простейшей альтернативой использованию\n", + "вложенного поля замены в строке формата является получение \n", + "среза строки, например:" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"{0} ...\".format(field[:maxwidth]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Еще одно преимущество такого подхода состоит в том, что он требует\n", + "меньшего объема ввода с клавиатуры." + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def extract_fields(line):\n", + " fields = []\n", + " field = \"\"\n", + " quote = None\n", + " for c in line:\n", + " if c in \"\\\"'\":\n", + " if quote is None: # начало строки в кавычках\n", + " quote = c\n", + " elif quote == c: # конец строки в кавычках\n", + " quote = None\n", + " else:\n", + " field += c\n", + " # другая кавычка внутри строки в кавычках\n", + " continue\n", + " if quote is None and c == \",\": # end of a field\n", + " fields.append(field)\n", + " field = \"\"\n", + " else:\n", + " field += c\n", + " # добавить символ в поле\n", + " if field:\n", + " fields.append(field) # добавить последнее поле в список\n", + " return fields" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Эта функция читает символы из строки один за другим и накапливает\n", + "список полей, где каждое поле – это строка без окружающих ее\n", + "кавычек. Функция способна обрабатывать поля, не заключенные в кавычки,\n", + "и поля, заключенные в кавычки или в апострофы, корректно обрабатывая\n", + "запятые и кавычки (апострофы в строках, заключенных в кавычки, и\n", + "кавычки в строках, заключенных в апострофы)." + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def escape_html(text):\n", + " text = text.replace(\"&\", \"&\")\n", + " text = text.replace(\"<\", \"<\")\n", + " text = text.replace(\">\", \">\")\n", + " return text" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Эта функция просто замещает каждый специальный символ HTML\n", + "соответствующей ему сущностью языка HTML. В первую очередь, конечно,\n", + "мы должны заменить символ амперсанда и угловые скобки, хотя порядок не\n", + "имеет никакого значения. \n", + "\n", "\n", "\n", "\n", "\n", + "# Упражнения\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "## Изменение вывода символов Юникода\n", + "
\n", + "\n", + "Измените программу `print_unicode.py` так, чтобы пользователь мог\n", + "вводить в командной строке несколько разных слов и получать\n", + "только те строки из таблицы символов Юникода, в которых содержатся все\n", + "слова, указанные пользователем. Это означает, что мы сможем вводить\n", + "такие команды:" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print_unicode_ans.py greek symbol" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "**Подсказка.**\n", + "Один из способов достижения поставленной цели состоит в том,\n", + "чтобы заменить переменную `word` (которая может хранить `0`, `None` \n", + "или строку) списком `words`. Не забудьте изменить информацию о порядке\n", + "использования. В результате изменений не более десяти строк\n", + "программного кода добавится и не более десяти строк изменится.\n", + "\n", + "\n", + "Имя файла: `print_unicode_ans.py`.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "## Изменение `quadratic.py`\n", + "
\n", + "\n", + "Измените программу `quadratic.py` так, чтобы она не выводила\n", + "коэффициенты со значением `0.0`, а отрицательные коэффициенты\n", + "выводились бы как `-n`, а не `+ - n`.\n", + "Имя файла: `quadratic_ans.py`.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "## Использование функции `escape()`\n", + "
\n", + "\n", + "Удалите функцию `escape_html()` из программы `cvs2html.py` и\n", + "используйте вместо нее функцию `xml.sax.saxutils.escape()` из модуля \n", + "`xml.sax.saxutils`.\n", + "\n", + "\n", + "\n", + "**Подсказка.**\n", + "Для этого потребуется добавить одну новую строку\n", + "(с инструкцией `import`), удалить пять строк (с ненужной функцией)\n", + "и изменить одну строку (задействовать функцию\n", + "`xml.sax.saxutils.escape()` вместо `escape_html()`).\n", + "\n", + "\n", + "Имя файла: `cvs2html_ans1.py`.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "## Добавление обработки параметров командной строки в `csv2html.py`\n", + "
\n", + "\n", + "Измените программу `cvs2html.py` еще раз и добавьте в нее новую\n", + "функцию с именем `process_options()`. Эта функция должна вызываться из\n", + "функции main() и возвращать кортеж с двумя значениями: \n", + "`maxwidth` (типа `int`) и `format` (типа `str`). При вызове функция\n", + "`process_options()` должна устанавливать `maxwidth` в значение по\n", + "умолчанию `100`, а строку `format` – в значение по умолчанию `\".0f\"`,\n", + "которое будет использоваться как спецификатор формата при выводе чисел.\n", + "Если пользователь вводит в командной строке `-h` или `--help`,\n", + "должно выводиться сообщение о порядке использования и возвращаться\n", + "кортеж `(None, None)`. (В этом случае функция `main()` ничего\n", + "делать не должна.) В противном случае функция должна прочитать\n", + "аргументы командной строки и выполнить соответствующие\n", + "присваивания. Например, устанавливать значение переменной `maxwidth`,\n", + "если задан аргумент `maxwidth=n`, и точно так же устанавливать \n", + "значение переменной `format`, если задан аргумент `format=s`. Ниже\n", + "приводится сеанс работы с программой, когда пользователь затребовал\n", + "инструкцию о порядке работы:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " Terminal> csv2html2_ans.py -h\n", + " usage:\n", + " csv2html.py [maxwidth=int] [format=str] < infile.csv > outfile.html\n", + " maxwidth - необязательное целое число. Если задано, определяет\n", + " максимальное число символов для строковых полей. В противном случае\n", + " используется значение по умолчанию 100.\n", + " \n", + " format - формат вывода чисел. Если не задан, по умолчанию используется\n", + " формат \".0f\".\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "А ниже приводится пример командной строки, в которой установ-\n", + "лены оба аргумента:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " Terminal> csv2html2_ans.py maxwidth=20 format=0.2f < mydata.csv > mydata.html\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "**Подсказка.**\n", + "Не забудьте изменить функцию `print_line()` так, чтобы она\n", + "использовала переменную `format` при выводе чисел – для этого вам\n", + "придется передавать функции дополнительный аргумент, добавить одну \n", + "строку и изменить еще одну строку. И это немного затронет функцию\n", + "`main()`. Функция `process_options()` должна содержать порядка\n", + "двадцати пяти строк (включая девять строк с текстом сообщения о\n", + "порядке использования).\n", + "\n", + "\n", + "Имя файла: `cvs2html_ans2.py`.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "\n", "\n", "\n", - "" + "\n", + "" ] } ], diff --git a/fig-collections/map_1.png b/fig-collections/map_1.png new file mode 100644 index 0000000..c7c43ea Binary files /dev/null and b/fig-collections/map_1.png differ diff --git a/fig-collections/seq_1.png b/fig-collections/seq_1.png new file mode 100644 index 0000000..ed06453 Binary files /dev/null and b/fig-collections/seq_1.png differ diff --git a/fig-collections/seq_2.png b/fig-collections/seq_2.png new file mode 100644 index 0000000..90d6f98 Binary files /dev/null and b/fig-collections/seq_2.png differ diff --git a/fig-collections/set_1.png b/fig-collections/set_1.png new file mode 100644 index 0000000..b45c11f Binary files /dev/null and b/fig-collections/set_1.png differ diff --git a/fig-collections/set_2.png b/fig-collections/set_2.png new file mode 100644 index 0000000..bdef9eb Binary files /dev/null and b/fig-collections/set_2.png differ diff --git a/fig-datatype/example_1.png b/fig-datatype/example_1.png new file mode 100644 index 0000000..4e14ad0 Binary files /dev/null and b/fig-datatype/example_1.png differ diff --git a/intro.ipynb b/intro.ipynb index 76b7326..15ff52a 100644 --- a/intro.ipynb +++ b/intro.ipynb @@ -10,15 +10,13 @@ " \n", "**С.В. Лемешевский** (email: `sergey.lemeshevsky@gmail.com`), Институт математики НАН Беларуси\n", "\n", - "Date: **Feb 22, 2020**\n", + "Date: **Feb 26, 2020**\n", "\n", "\n", "\n", "\n", "\n", "\n", - "\n", - "\n", "# Установка\n", "
\n", "\n", @@ -1462,8 +1460,7 @@ "![](fig-intro/jupyter_1.png)\n", "\n", "\n", - "### Jupyter Notebook\n", - "\n", + "## Jupyter Notebook\n", "
\n", "\n", "Кроме интерактивной консоли Jupyter также предоставляет веб-приложение\n", @@ -1529,7 +1526,7 @@ "сохраняются в формате JSON со специальным разрешением `ipynb`. Файл\n", "Jupyter Notebook не является чистым кодом на Python, но при\n", "необходимости код на Python можно легко выделить из блокнота используя\n", - "либо меню «File ➤ Download as ➤ Python» или с помощью утилиты\n", + "либо меню **File | Download as | Python** или с помощью утилиты\n", "`nbconvert`.\n", "\n", "\n", @@ -1581,8 +1578,6 @@ "\n", "
\n", "\n", - "\n", - "\n", "Используя меню и панель инструментов, ячейки можно добавлять,\n", "удалять, перемещать вверх и вниз, вырезать и вставлять и т.д. Эти\n", "функции также связаны с сочетаниями клавиш, которые удобны и\n", @@ -1599,11 +1594,9 @@ "доступными через панель инструментов и меню. \n", "\n", "\n", - "\n", - "
\n", "\n", + "## Таблица 1 : Клавиши
\n", "\n", - "**Таблица 1.** \n", "\n", "\n", "\n", @@ -1624,19 +1617,19 @@ "\n", "\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", "
Enter Войти в режим редактирования ячейки
Escape Выйти из режима редактирования ячейки
Shift-Enter Выполнить ячейку
h Показать окно помощи со списком сочиетаний клавиш
h Показать окно помощи со списком сочетаний клавиш
0-0 Перезапустить ядро
i-i Прервать выполнение ячейки
s Сохранить блокнот
\n", - "\n", + "\n", "\n", "Во время выполнения ячейки блокнота номер ячейки обозначается\n", "звездочкой (`In [*]`), а индикатор в правом верхнем углу страницы\n", "сигнализирует о том, что ядро IPython занято. Прервать выполнение\n", - "ячейки можно через меню «Kernel ➤ Interrupt» или сочетанием клавиш\n", - "`i-i` в командном режиме (т.е., дважды нажать клавишу `i`). В таблице 1\n", + "ячейки можно через меню **Kernel | Interrupt** или сочетанием клавиш\n", + "`i-i` в командном режиме (т.е., дважды нажать клавишу `i`). В таблице [table:1](#table:1)\n", "представлены наиболее популярные сочетания клавиш командного режима\n", "Jupyter Notebook.\n", "\n", @@ -2050,7 +2043,7 @@ "\n", "Каждую панель можно настроить для отображения или скрытия в\n", "зависимости от предпочтений и потребностей пользователя, используя\n", - "меню «View ➤ Panes». \n", + "меню **View | Panes**.\n", "\n", "### Редактор исходного кода\n", "\n", @@ -2097,8 +2090,8 @@ "поскольку она позволяет исследовать значения переменных после\n", "завершения выполнения сценария. Spyder поддерживает одновременное\n", "открытие нескольких консолей Python и IPython, и, например, новую\n", - "консоль IPython можно запустить через меню «Consoles ➤ Open an IPython\n", - "console». При запуске сценария из редактора нажатием клавиши F5 или\n", + "консоль IPython можно запустить через меню **Consoles | Open an IPython\n", + "console**. При запуске сценария из редактора нажатием клавиши F5 или\n", "кнопки запуска на панели инструментов сценарий по умолчанию\n", "запускается в самой последней активированной консоли. Это позволяет\n", "поддерживать разные консоли с независимыми пространствами имен для\n", diff --git a/src-datatype/csv2html.py b/src-datatype/csv2html.py new file mode 100644 index 0000000..6043b61 --- /dev/null +++ b/src-datatype/csv2html.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +def main(): + maxwidth = 100 + print_start() + count = 0 + while True: + try: + line = input() + if count == 0: + color = "lightgreen" + elif count % 2: + color = "white" + else: + color = "lightyellow" + print_line(line, color, maxwidth) + count += 1 + except EOFError: + break + print_end() + +def print_start(): + print("") + +def print_end(): + print("
") + +def print_line(line, color, maxwidth): + print("".format(color)) + fields = extract_fields(line) + for field in fields: + if not field: + print("") + else: + number = field.replace(",", "") + try: + x = float(number) + print("{0:d}".format(round(x))) + except ValueError: + field = field.title() + field = field.replace(" And ", " and ") + field = escape_html(field) + if len(field) <= maxwidth: + print("{0}".format(field)) + else: + print("{0:.{1}} ...".format(field, maxwidth)) + print("") + +def extract_fields(line): + fields = [] + field = "" + quote = None + for c in line: + if c in "\"'": + if quote is None: # начало строки в кавычках + quote = c + elif quote == c: # конец строки в кавычках + quote = None + else: + field += c + # другая кавычка внутри строки в кавычках + continue + if quote is None and c == ",": # end of a field + fields.append(field) + field = "" + else: + field += c + # добавить символ в поле + if field: + fields.append(field) # добавить последнее поле в список + return fields + +def escape_html(text): + text = text.replace("&", "&") + text = text.replace("<", "<") + text = text.replace(">", ">") + return text + + +main() diff --git a/src-datatype/csv2html.py~ b/src-datatype/csv2html.py~ new file mode 100644 index 0000000..b4d4ce4 --- /dev/null +++ b/src-datatype/csv2html.py~ @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +def main(): + maxwidth = 100 + print_start() + count = 0 + while True: + try: + line = input() + if count == 0: + color = "lightgreen" + elif count % 2: + color = "white" + else: + color = "lightyellow" + print_line(line, color, maxwidth) + count += 1 + except EOFError: + break + print_end() + +def print_start(): + print("") + +def print_end(): + print("
") + +def print_line(line, color, maxwidth): + print("".format(color)) + fields = extract_fields(line) + for field in fields: + if not field: + print("") + else: + number = field.replace(",", "") + try: + x = float(number) + print("{0:d}".format(round(x))) + except ValueError: + field = field.title() + field = field.replace(" And ", " and ") + field = escape_html(field) + if len(field) <= maxwidth: + print("{0}".format(field)) + else: + print("{0:.{1}} ...".format(field, maxwidth)) + print("") + +def extract_fields(line): + fields = [] + field = "" + quote = None + for c in line: + if c in "\"'": + if quote is None: # начало строки в кавычках + quote = c + elif quote == c: # конец строки в кавычках + quote = None + else: + field += c + # другая кавычка внутри строки в кавычках + continue + if quote is None and c == ",": # end of a field + fields.append(field) + field = "" + else: + field += c + # добавить символ в поле + if field: + fields.append(field) # добавить последнее поле в список + return fields + +def escape_html(text): + text = text.replace("&", "&") + text = text.replace("<", "<") + text = text.replace(">", ">") + return text + +if __name__ == '__main__': + main() diff --git a/src-datatype/print_unicode.py b/src-datatype/print_unicode.py new file mode 100644 index 0000000..f69c980 --- /dev/null +++ b/src-datatype/print_unicode.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +import sys +import unicodedata + +def print_unicode_table(word): + print("decimal hex chr {0:^40}".format("name")) + print("------- ----- --- {0:-<40}".format("")) + + code = ord(" ") + end = sys.maxunicode + + while code < end: + c = chr(code) + name = unicodedata.name(c, "*** unknown ***") + if word is None or word in name.lower(): + print("{0:7} {0:5X} {0:^3c} {1}".format(code, name.title())) + code += 1 +# End print_unicode_table + +# Start main script +word = None + +if len(sys.argv) > 1: + if sys.argv[1] in ("-h", "--help"): + print("usage: {0} [string]".format(sys.argv[0])) + word = 0 + else: + word = sys.argv[1].lower() + +if word != 0: + print_unicode_table(word) + +#End main script diff --git a/src-datatype/print_unicode.py~ b/src-datatype/print_unicode.py~ new file mode 100644 index 0000000..4fbbac7 --- /dev/null +++ b/src-datatype/print_unicode.py~ @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +import sys +import unicodedata + +def print_unicode_table(word): + print("decimal hex chr {0:^40}".format("name")) + print("------- ----- --- {0:-<40}".format("")) + + code = ord(" ") + end = sys.maxunicode + + while code < end: + c = chr(code) + name = unicodedata.name(c, "*** unknown ***") + if word is None or word in name.lower(): + print("{0:7} {0:5X} {0:^3c} {1}".format(code, name.title())) + code += 1 + + +word = None + +if len(sys.argv) > 1: + if sys.argv[1] in ("-h", "--help"): + print("usage: {0} [string]".format(sys.argv[0])) + word = 0 + else: + word = sys.argv[1].lower() + +if word != 0: + print_unicode_table(word) diff --git a/src-datatype/quadratic.py b/src-datatype/quadratic.py index 505b345..77bcc69 100644 --- a/src-datatype/quadratic.py +++ b/src-datatype/quadratic.py @@ -18,6 +18,7 @@ def get_float(msg, allow_zero): return x # End get_float + # Start 1st block print("ax\N{SUPERSCRIPT TWO} + bx + c = 0") a = get_float("enter a: ", False) @@ -34,7 +35,7 @@ if discriminant == 0: else: if discriminant > 0: root = math.sqrt(discriminant) - else: # discriminant < 0 + else: # discriminant < 0 root = cmath.sqrt(discriminant) x1 = (-b + root) / (2 * a) x2 = (-b - root) / (2 * a) diff --git a/src-datatype/quadratic.py~ b/src-datatype/quadratic.py~ new file mode 100644 index 0000000..505b345 --- /dev/null +++ b/src-datatype/quadratic.py~ @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +import cmath +import math +import sys + +# Start get_float +def get_float(msg, allow_zero): + x = None + while x is None: + try: + x = float(input(msg)) + if not allow_zero and abs(x) < sys.float_info.epsilon: + print("zero is not allowed") + x = None + + except ValueError as err: + print(err) + return x +# End get_float + +# Start 1st block +print("ax\N{SUPERSCRIPT TWO} + bx + c = 0") +a = get_float("enter a: ", False) +b = get_float("enter b: ", False) +c = get_float("enter c: ", False) +# End 1st block + +# Start 2d block +x1 = None +x2 = None +discriminant = (b ** 2) - (4 * a * c) +if discriminant == 0: + x1 = -(b / (2 * a)) +else: + if discriminant > 0: + root = math.sqrt(discriminant) + else: # discriminant < 0 + root = cmath.sqrt(discriminant) + x1 = (-b + root) / (2 * a) + x2 = (-b - root) / (2 * a) +# End 2d block + +# Start 3d block +equation = ("{0}x\N{SUPERSCRIPT TWO} + {1}x + {2} = 0" + " \N{RIGHTWARDS ARROW} x = {3}").format(a, b, c, x1) +if x2 is not None: + equation += " or x = {0}".format(x2) +print(equation) +# End 3d block diff --git a/src-datatype/sample.csv b/src-datatype/sample.csv new file mode 100644 index 0000000..91c5949 --- /dev/null +++ b/src-datatype/sample.csv @@ -0,0 +1,5 @@ +"COUNTRY",2000,2001,2002,2003,2004 +"ANTIGUA AND BARBUDA",0,0,0,0,0 +"ARGENTINA",37,35,33,36,39 +"BAHAMAS, THE",1,1,1,1,1 +"BAHRAIN",5,6,6,6,6 \ No newline at end of file diff --git a/src-datatype/sample.csv~ b/src-datatype/sample.csv~ new file mode 100644 index 0000000..91c5949 --- /dev/null +++ b/src-datatype/sample.csv~ @@ -0,0 +1,5 @@ +"COUNTRY",2000,2001,2002,2003,2004 +"ANTIGUA AND BARBUDA",0,0,0,0,0 +"ARGENTINA",37,35,33,36,39 +"BAHAMAS, THE",1,1,1,1,1 +"BAHRAIN",5,6,6,6,6 \ No newline at end of file diff --git a/src-datatype/sample.html b/src-datatype/sample.html new file mode 100644 index 0000000..4f713a6 --- /dev/null +++ b/src-datatype/sample.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
"Country"20002001200220032004
"Antigua and Barbuda"00000
"Argentina"3735333639
"Bahamas, The"11111
"Bahrain"56666
diff --git a/src-datatype/sample.html~ b/src-datatype/sample.html~ new file mode 100644 index 0000000..4f713a6 --- /dev/null +++ b/src-datatype/sample.html~ @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
"Country"20002001200220032004
"Antigua and Barbuda"00000
"Argentina"3735333639
"Bahamas, The"11111
"Bahrain"56666