{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Программирование для всех (основы работы с Python)\n", "\n", "*Алла Тамбовцева, НИУ ВШЭ*\n", "\n", "*Данный ноутбук частично основан на [лекции](http://nbviewer.math-hse.info/github/ischurov/pythonhse/blob/master/Lecture%202.ipynb) Щурова И.В., курс «Программирование на языке Python для сбора и анализа данных» (НИУ ВШЭ).*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Списки и цикл `for`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Знакомство со списками" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Создадим список `age` из значений возраста респондентов. Элементы списка перечисляются в квадратных скобках через запятую:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 20]\n" ] } ], "source": [ "age = [25, 35, 48, 20]\n", "print(age)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Список может содержать элементы любого типа, необязательно числового. Например, мы можем создать список имён `name`, полностью состоящий из строк:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Ann', 'Nick', 'Ben', 'George', 'James']\n" ] } ], "source": [ "name = [\"Ann\", \"Nick\", \"Ben\", \"George\", \"James\"]\n", "print(name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "А можем создать список, состоящий из элементов разных типов. Представим, что не очень сознательный исследователь закодировал пропущенные значения в списке текстом, написав «нет ответа»:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[23, 25, 'no answer', 32]\n" ] } ], "source": [ "mixed = [23, 25, \"no answer\", 32]\n", "print(mixed)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Элементы разных типов спокойно уживаются в списке: Python не меняет тип элементов. Все элементы, которые являются строками, останутся строками, а числа – числами. Список может иметь более сложную структуру, например, представлять собой список списков:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1, 2, 3], [4, 5]]\n" ] } ], "source": [ "L = [[1, 2, 3], [4, 5]]\n", "print(L)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "У списка всегда есть длина – количество элементов в нём. Длина определяется с помощью функции `len()`." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(age) # четыре элемента" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если список пустой, то, как несложно догадаться, его длина равна нулю:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "empty = []\n", "len(empty)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Раз список состоит из элементов, к ним можно обращаться по отдельности. Главное, нужно помнить, что нумерация в Python начинается с нуля, а не с единицы. Существует несколько обоснований, почему это так, с одним из них мы познакомимся чуть позже, когда будем обсуждать срезы." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "25" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "age[0] # первый элемент age" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Порядковый номер элемента в списке называется индексом. Далее, чтобы не путаться, будем разделять термины: порядковые числительные останутся для обозначения номера элемента в нашем обычном понимании, а индексы – для обозначения номера элемента в Python. Например, если нас будет интересовать элемент 35 из списка `age`, мы можем сказать, что нас интересует второй элемент или элемент с индексом 1:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 20]\n", "35\n" ] } ], "source": [ "print(age)\n", "print(age[1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если элемента с интересующим нас индексом в списке нет, Python выдаст ошибку, а точнее, исключение, под названием `IndexError`." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "ename": "IndexError", "evalue": "list index out of range", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mage\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mIndexError\u001b[0m: list index out of range" ] } ], "source": [ "age[5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "А как обратиться к последнему элементу списка, да так, чтобы код был универсальным – работал и в случае, когда мы изменим длину списка? Давайте подумаем. Длина списка `age`, как мы уже убедились, равна 4, но нумерация самих элементов начинается с нуля. Поэтому: " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "20" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "age[len(age)-1] # последний элемент - 20" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Конечно, в том, что нумерация элементов в списке начинается с нуля, есть некоторое неудобство – индекс последнего элемента не совпадает с длиной списка. Но, на самом деле, обращаться к последнему элементу списка можно и по-другому: считать элементы с конца!" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "20" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "age[-1] # последний элемент - он же первый с конца" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Отрицательные индексы элементов в Python – абсолютно нормальная вещь. Можем так же получить второй элемент с конца:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "48" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "age[-2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Изменение и добавление элементов" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Список – изменяемый тип в Python (*mutable*). Это означает, что список можно изменять, не перезаписывая его, то есть не создавая новую переменную с тем же названием. Для сравнения: объекты, с которыми мы работали ранее, были неизменяемыми. Для того, чтобы перезаписать значение числовой переменной `x`, нужно было явно задействовать оператор присваивания `=`:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "# было 2\n", "x = 2" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3\n" ] } ], "source": [ "# стало 3\n", "x = x + 1\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Со списками всё обстоит иначе: мы можем обращаться к уже существующему списку, выбирать в нём элемент и заменять его, не перезаписывая весь список «с нуля». Например, заменим последний элемент списка `age` на число 30:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 30]\n" ] } ], "source": [ "age[-1] = 30\n", "print(age) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "А ещё можно дописывать элементы в конец списка. Для этого существует два метода: `.append()` и `.extend()`. Метод `.append()` используется для присоединения одного элемента, `.extend()` – для добавления целого списка. " ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 30, 27]\n" ] } ], "source": [ "age.append(27) # добавили 27\n", "print(age) " ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 30, 27, 43, 33]\n" ] } ], "source": [ "age.extend([43, 33]) # добавили 43 и 33\n", "print(age) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Важный момент: методы `.append()` и `extend()`, да и почти все методы, которые затрагивают исходный список, молча вносят изменения в сам список, а не возвращают его обновлённую копию. Возвращают они пустое значение `None`, поэтому использовать одновременно, например, `.append()` и `=` для изменения списка – ошибочное решение:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None\n" ] } ], "source": [ "# якобы добавляем 90 и сохраняем обновленный список в age2\n", "\n", "age2 = age.append(90) \n", "print(age2) # но нет" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Методы `.append()` и `.extend()` приписывают значения только в конец списка. Для добавления элементов в любое другое место существует метод `.insert()`, он «втискивает» элемент на место с указанным индексом:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 30, 27, 43, 33, 90]\n", "[25, 35, 48, 29, 30, 27, 43, 33, 90]\n" ] } ], "source": [ "print(age) # до\n", "\n", "age.insert(3, 29) # добавили 29 четвертым элементом (индекс 3)\n", "\n", "print(age) # после " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Также списки можно склеивать, то есть использовать операцию, которая называется *конкатенацией*. В этом смысле списки очень похожи на строки, и для их конкатенации тоже используется знак `+` (история про перегрузку операторов, когда одни и те же операторы выполняют разные операции на разных типах, мы уже такое обсуждали):" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[4, 5, 6, 7, 8, 9]\n" ] } ], "source": [ "L = [4, 5, 6] + [7, 8, 9] \n", "print(L)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Запись через `+` кажется очень интуитивной и заманчивой, но не стоит ей часто пользоваться, когда списки очень большие и их много. При такой конкатенации списков происходит создание нового списка, который «склеивается» из отдельных частей, чего не происходит при использовании `.extend()`: там элементы просто дописываются в уже существующий список. Поэтому приписывание одного списка в конец другого быстрее и эффективнее делать именно через `.extend()`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "На данный момент мы достаточно хорошо познакомились со списками. Но списки не так просты, как кажется. И это снова связано с тем, что список – изменяемый тип. Давайте попробуем сделать следующее: скопировать один список в другой путем присваивания." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 29, 30, 27, 43, 33, 90] [25, 35, 48, 29, 30, 27, 43, 33, 90]\n" ] } ], "source": [ "age2 = age # сохранили список L1 в L2\n", "print(age, age2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Пока все ожидаемо. А теперь допишем в `age2` элемент 18:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "age2.append(18)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "И сравним оба списка:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 29, 30, 27, 43, 33, 90, 18] [25, 35, 48, 29, 30, 27, 43, 33, 90, 18]\n" ] } ], "source": [ "print(age, age2) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Несмотря на то, что список `age` мы не трогали, он изменился точно так же, как и список `age2`! Что произошло? На самом деле, когда мы записали `age2 = age`, мы скопировали не сам список, а ссылку на него. Другими словами, проводя аналогию с папкой и ярлыком, вместо того, чтобы создать новую папку `age2` с элементами, такими же, как в `age`, мы создали ярлык `age2`, который сам по себе ничего не представляет, а просто ссылается на папку `age`. \n", "\n", "Так как же тогда копировать списки? Можно воспользоваться методом `.copy()`. " ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 29, 30, 27, 43, 33, 90, 18]\n", "[25, 35, 48, 29, 30, 27, 43, 33, 90, 18, 18]\n" ] } ], "source": [ "age2 = age.copy() \n", "age2.append(18)\n", "\n", "print(age)\n", "print(age2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Срезы (slices)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Мы уже познакомились с тем, как выбирать отдельные элементы из списка, однако мы ещё не обсудили, как выбирать несколько элементов подряд. Такие части списков называются срезами (*slices*). Индексы элементов, которые должны войти в срез, указываются в квадратных скобках, через двоеточие (`начало` : `конец`)." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[48, 29, 30]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "age[2:5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Важно: правый конец не включается в срез! В срез выше вошли элементы с индексами 2, 3, 4, элемент с индексом 5 включён не был." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если мы хотим задать только начало или конец среза, один из индексов легко можно опустить: " ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[48, 29, 30, 27, 43, 33, 90, 18]\n", "[25, 35, 48, 29, 30]\n" ] } ], "source": [ "print(age[2:])\n", "print(age[:5])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Тут мы подходим к тому, [почему](http://python-history.blogspot.ru/2013/10/why-python-uses-0-based-indexing.html) нумерация элементов в Python начинается с нуля. В частности, для удобных срезов. Если нам нужны первые два элемента списка, нам не нужно долго думать и сдвигать номера элементов на единицу, достаточно просто написать, например, `age[:2]`. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Можно ли сделать срез, который будет включать в себя весь список? Легко!" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[25, 35, 48, 29, 30, 27, 43, 33, 90, 18]" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "age[:] # опускаем все индексы" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Срезы можно задействовать и для изменения списка:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 35, 48, 29, 30, 27, 43, 33, 90, 18]\n", "[25, 28, 26, 29, 30, 27, 43, 33, 90, 18]\n" ] } ], "source": [ "print(age)\n", "\n", "age[1:3] = [28, 26] # заменим элементы с индексами 1 и 2\n", "\n", "print(age)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Длина списка, на который мы заменяем срез, не обязательно должна совпадать с длиной среза. Можно взять список с большим числом элементов, тогда исходный список расширится, а можно с меньшим – список сузится. Замены остальных элементов при этом не произойдет, новый срез просто «вклинится» в середину списка." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25, 18, 32, 45, 29, 30, 27, 43, 33, 90, 18]\n" ] } ], "source": [ "age[1:3] = [18, 32, 45]\n", "print(age)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Цикл `for`\n", "\n", "Раз есть списки, хочется научиться «пробегаться» по их элементам. Например, выводить на экран не весь список `age` сразу, а постепенно, каждый элемент с новой строки. Для этого существуют циклы. Они позволяют выполнять одну и ту же операцию или набор операций несколько раз, не копируя один и тот же код и не запуская его заново. \n", "\n", "Рассмотрим цикл `for`. Создадим список `nums` и последовательно выведем его элементы на экран:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "nums = [1, 10, 23, -8, 6] " ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "10\n", "23\n", "-8\n", "6\n" ] } ], "source": [ "for i in nums:\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Как устроен цикл выше? Кодом выше мы доносим до Python мысль: пробегайся по всем элементам списка `age` и выводи каждый элемент на экран. Вообще любой цикл `for` имеет такую структуру: сначала указывается, по каким значениям нужно пробегаться, а потом, что нужно делать. Действия, которые нужно выполнить в цикле, указываются после двоеточия в `for` – эта часть назвается *телом* цикла. \n", "\n", "Буквы в конструкции `for` могут быть любые, совсем необязательно брать букву `i`. Python сам поймёт, просто по синтаксису конструкции, что мы имеем в виду, запуская цикл." ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "10\n", "23\n", "-8\n", "6\n" ] } ], "source": [ "# element вместо i\n", "\n", "for element in nums:\n", " print(element)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Можем выводить не сами элементы, а, например, результаты возведения их в квадрат:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 1\n", "10 100\n", "23 529\n", "-8 64\n", "6 36\n" ] } ], "source": [ "for i in nums:\n", " print(i, i ** 2) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Давайте, используя цикл, создадим новый список на основе старого." ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "squares = [] # пока пустой список\n", "for n in nums:\n", " squares.append(n ** 2) # постепенно записываем элементы" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 100, 529, 64, 36]\n" ] } ], "source": [ "print(squares)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Конечно, циклы нужны не только для того, чтобы работать со списками. С помощью циклом можно решить любую задачу, которая требует повторения одинаковых действий. Рассмотрим такую задачу.\n", "\n", "С приходом весны питон решил каждый день выползать погреться на солнышко. Однако он знал, что солнце весной довольно активное, и поэтому разработал такую схему: в первый день он греется одну минуту, а в каждый последующий день увеличивает время пребывания на солнце на 3 минуты. Нам нужно написать код, который позволит вычислять, сколько минут питон будет тратить на солнечные ванны в некоторый выбранный день." ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 1\n", "2 4\n", "3 7\n", "4 10\n", "5 13\n", "6 16\n", "7 19\n" ] } ], "source": [ "# создадим список с номерами дней\n", "# зафиксируем начальное значение времени t = 1 минута\n", "\n", "days = [2, 3, 4, 5, 6, 7] \n", "t = 1\n", "print(1, t) \n", "\n", "# теперь будем обновлять значение t в цикле\n", "# и выводить на экран номер дня и время\n", "\n", "for day in days: \n", " t = t + 3\n", " print(day, t)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Функция `range()`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "На самом деле, можно было поступить ещё проще. В Python есть функция `range()`, которая позволяет перебирать целые числа на заданном промежутке, не создавая при этом сам список чисел." ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "range(0, 7)" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "range(0, 7)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Есть небольшая проблема: из-за того, что список с числами не создаётся и не занимает память, явно элементы внутри `range()` мы не увидим. Можно преобразовать результат в список:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 2, 3, 4, 5, 6]" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(0, 7))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Правый конец заданного в `range()` промежутка не включается, будьте бдительны. В примере выше на экран были выведены числа от 0 до 6, число 7 включено не было. \n", "\n", "При использовании `range()` в циклах преобразовывать результат в список уже не нужно, в примере выше мы просто хотели посмотреть на объект изнутри. Применим `range()` к нашей задаче про питона:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 1\n", "2 4\n", "3 7\n", "4 10\n", "5 13\n", "6 16\n", "7 19\n" ] } ], "source": [ "t = 1\n", "print(1, t) \n", "\n", "for day in range(2, 8): \n", " t = t + 3\n", " print(day, t) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Полезный факт 1: если нас интересуют числа на промежутке, начиная с нуля, в `range()` левый конец можно не указывать, 0 будет выбран по умолчанию." ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 2, 3, 4]" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Полезный факт 2: внутри `range()` можно указать любой целочисленный шаг для получения последовательности чисел." ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 2, 4, 6, 8, 10, 12, 14]" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# шаг 2, только чётные числа от 0 до 16, исключая 16\n", "list(range(0, 16, 2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Полезный факт 3: шаг внутри `range()` может быть отрицательным, тогда мы получим последовательность, отсортированную по убыванию. В таком случае сначала нужно указывать правый конец интервала, а потом – левый." ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[16, 14, 12, 10, 8, 6, 4, 2]" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(16, 0, -2)) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если сначала указать меньшее значение, то мы получим пустой список. Это происходит потому, что мы даём Python противоречивые указания – `range()` двигается всегда слева направо, а отрицательный шаг предполагает движение справа налево:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(0, 16, -2)) " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" } }, "nbformat": 4, "nbformat_minor": 2 }