#!/usr/bin/env python # coding: utf-8 # # Основы программирования в Python # # *Алла Тамбовцева, НИУ ВШЭ* # # *Данный ноутбук основан на [лекции](http://python.math-hse.info:8080/github/ischurov/pythonhse/blob/master/Lecture%201.ipynb) Щурова И.В., [курс](http://math-info.hse.ru/s15/m) «Программирование на языке Python для сбора и анализа данных» (НИУ ВШЭ).* # ## Python как калькулятор, переменные и типы переменных # ### Python как калькулятор # Привычные арифметические действия (сложение, вычитание, умножение, деление) в Python выглядят так же, как и в обычных калькуляторах: # In[1]: 1 + 2 # сложение # In[2]: 2 * 4 - 9 # умножение и вычитание # In[3]: 23 / 2 # деление # Однако с делением все не так просто: Python 3 всегда будет выдавать результат в виде числа с плавающей точкой (*float*), даже тогда, когда ожидается целочисленный ответ. Например: # In[4]: 6 / 2 # не 3 # Получился дробный результат, где дробная часть равна 0. Как быть, если нужен ответ в виде целого числа? Можно воспользоваться целочисленным делением. # In[5]: 6 // 2 # теперь 3 # Тут важно помнить, что при использовании оператора `//` дробная часть всегда будет просто отбрасываться – никакого округления происходить не будет. # In[6]: 6 // 4 # от 1.5 осталось 1 # В Python 2 обычное деление (с помощью `/`) было целочисленным. Для того чтобы получить привычные результаты деления, нужно было либо импортировать обычное деление из модуля `__future__`, который позволяет использовать функционал более новых версий Python (см. [здесь](http://rextester.com/VMMS70343)), либо использовать другие хитрости, например, делить число с плавающей точкой на целое (см. [здесь](http://rextester.com/YJZV11974)). # # *Примечание:* для того, чтобы сравнивать исполнение одного и того же кода в Python 3 и Python 2 совсем необязательно устанавливать обе версии на компьютер. Можно воспользоваться онлайн-компиляторами (например, http://rextester.com: выбирать Python или Python 3) и запускать код прямо в браузере. Речь идет, конечно, о небольших фрагментах кода. Полноценно работать в них, не устанавливая Python, будет неудобно. Но для нескольких строк для сравнения как раз. # Что еще можно делать с числами? Возводить в степень и извлекать из них корень. При расчетах на калькуляторе и в R для возведения числа в степень мы обычно используем символ `^`. Попробуем! # In[7]: 2 ^ 3 # ой # Получилось что-то неожиданное. В Python оператор `^` используется для побитного сложения по модулю два. Для возведения числа в степень потребуется `**` (кстати, в R тоже для возведения в степень можно использовать двойную звездочку): # In[8]: 2 ** 3 # как нужно # Теперь попробуем извлечь квадратный корень из числа с помощью привычного `sqrt`. # In[9]: sqrt(9) # не получается! # Python пишет, что не знает, что такое `sqrt`. В каких случаях Python может такое писать? Например, если мы опечатались в названии функции (Python не понимает, что мы от него хотим) или если мы пытаемся обратиться к функции, которая не является базовой (Python не знает, откуда ее брать). В нашем случае у нас вторая проблема. Функция для вычисления квадратного корня из числа хранится в специальном модуле `math`. Этот модуль стандартный, дополнительно устанавливать его не нужно. Но для того, чтобы воспользоваться этой функцией, нужно сначала импортировать модуль, а потом вызвать из него функцию `sqrt` (для тех, кто работал в R -- процедура, аналогичная `library()`. # In[10]: import math # импортируем модуль math # In[11]: math.sqrt(9) # теперь все работает # Если из `math` нам нужна только одна функция `sqrt` , можно извлечь только ее, и тогда прописывать название модуля перед функцией не понадобится: # In[12]: from math import sqrt sqrt(16) # так тоже работает # В `math` есть много полезных функций для вычислений. Чтобы посмотреть, какие функции там есть, после импортирования всего модуля через `import math` можно набрать `math.` и нажать на *Tab* (табуляция, кнопка над *Caps Lock*). Помимо квадратного корня этот модуль поможет вычислить логарифм (натуральный и не только), синус, косинус и так далее. # In[13]: math.log(2) # натуральный логарифм # In[14]: math.log10(100) # десятичный логарифм (логарифм по основанию 10) # In[15]: math.sin(0) # синус # А еще из `math` можно импортировать константы $\pi$ и $e$: # In[16]: from math import pi, exp # можно сразу несколько - перечислить через запятую # In[17]: pi # In[18]: exp(1) # С чем еще можно столкнуться, выполняя вычисления в Python? С такими вещами: # In[19]: 1 / 18 ** 25 # Результат выше – компьютерная форма экспоненциальной записи числа. Возможно, тот, кто считал что-то на научных или инженерных калькуляторах, уже сталкивался с такой записью. Здесь `e-32` – это $10^{-32}$, а вся запись означает $4.1513310942010236 \cdot 10^{-32}$, то есть примерно $4.15 \cdot 10^{-32}$. Если бы число было очень большим, `e` стояло бы в положительной степени. # # Такая компьютерная форма записи числа отчасти помогает понять, почему дробные числа называются числами с плавающей точкой (*float*). Возьмем число попроще, например, $12.34$. Его можно записать как $12.34$, как $1.234 \cdot 10$, как $123.4 \cdot 10^{-1}$, $1234 \cdot 10^{-2}$ и так далее. Точка, отделяющая дробную часть от целой, будет "плавать", однако само число при этом меняться не будет, будут меняться только множители ‒ разные степени десятки. # С числами с плавающей точкой связана еще одна сложность — округление. На первый взгляд, все хорошо: # In[20]: round(12.6) # округлим до целого # In[21]: round(12.53, 1) # округлим до первого знака после запятой # С другой стороны, могут возникнуть странности: # In[22]: round(2.50) # не 3 # In[23]: round(3.525, 2) # не 3.53 # Эти странности связаны с тем, что число, которое мы видим (например, 3.525), не совпадает с тем, которое хранится в компьютере, потому что оно при сохранении преобразовывается и превращается из точного 3.525 в такое: # In[24]: from decimal import Decimal Decimal(3.525) # И такое число будет законно округляться до 3.52 по правилам арифметического округления. Не то чтобы это очень важная информация, которую нужно всегда иметь в виду, но знать про нее полезно, просто чтобы не пугаться и не удивляться неожиданным результатам. # ### Переменные # Переменные в программировании похожи на переменные в математике. Кроме того, их можно рассматривать как хранилища значений – «коробки», в которые мы что-то кладем. Python, в отличие от некоторых языков программирования (C, C++, Java), сам распознает что мы «кладем в коробку»: число, целое число, текст, список чисел... Поэтому при создании переменной нам не нужно указывать ее тип. # In[25]: x = 2 y = 3 # In[26]: print(x) print(y) # Значения переменных мы можем обновлять – изменить значение и сохранить в переменную с тем же названием. # In[27]: x = x + 1 # возьмем значение x, увеличим на 1 и сохраним изменения в переменной x # In[28]: y = y * 2 # возьмем значение y, увеличим в 2 раза и сохраним изменения # In[29]: print(x, y) # Рассмотрим такую задачу. Пришла весна и решили мы заняться бегом по такой схеме: каждый день мы пробегаем столько, сколько в сумме за два предыдущих дня. При этом первые два дня мы морально готовимся: топчемся на месте и символически проходим по одному метру (полшага назад и полшага вперед). Если мы будем записывать все пройденные нами расстояния в ряд, мы получим последовательность из [чисел Фибоначчи](https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8). Давайте напишем код, который будет считать, сколько метров мы будем пробегать в следующий день. # Сначала создадим переменные, в которые сохраним данные по первым двум дням. # In[30]: b = 1 # день 1 - готовимся бегать, "бежим" 1 метр i = 1 # номер дня, когда начинаем бегать bnext = 1 # день 2 - готовимся бегать, "бежим" 1 метр i = i + 1 # перешли ко второму дню, увеличили i на 1 # In[31]: res = b + bnext # в следующий день пробегаем столько же, сколько за два предыдущих i = i + 1 # перешли к следующему дню, увеличили i на 1 b = bnext # значение b нам уже не нужно, сдвигаемся к следующему дню - записываем bnext bnext = res # запомнили полученное значение res print(i, bnext) # выводим на экран номер дня и расстояние, которое нужно пробежать # Теперь можно прогонять предыдущую ячейку много раз (через *Ctrl + Enter*) и получать результат по каждому дню. Например, на 20 день мы будем пробегать уже нормальное расстояние — 6765 метров, почти 7 километров. Конечно, прогонять одну и ту ячейку много раз неудобно и странно, но о том, как считать числа Фибоначчи более рационально, мы поговорим, когда будем разбирать циклы. # # **Важно:** если бы не разбили наш код на части (на две ячейки), ничего бы при повторном запуске ячейки не произошло — переменным *b*, *bnext* и *i* заново присваивались бы значения 1, и движения вперед бы не происходило. # ### Типы переменных и преобразование типов # Типы переменных (не путать с data types): # # * числовой c плавающей точкой (*float*) # * целочисленный (*integer*) # * строковый или текстовый (*string*) # * логический (*boolean*): только два значения True и False # # *Примечание:* в R вместо *float* был numeric, вместо *string* – *character*, вместо *boolean* – *logical*. # Посмотрим, как определить тип переменной: # In[32]: x = 2.34 type(x) # In[33]: y = 2 type(y) # In[34]: r = 'hello' type(r) # In[36]: l = True type(l) # Иногда требуется преобразовать тип переменной, например, из числа с плавающей точкой сделать целое число. Зачем это бывает нужно? Для удобства и для более корректной выдачи результатов. Например, у нас есть база данных по респондентам, в которой указан их год рождения, и мы хотим добавить столбец с возрастом респондентов (числом полных лет). Из-за того, что кто-то ввел год в виде 1993.0, возраст при вычислениях тоже получится числом с плавающей точкой — 25.0. Так как мы знаем, что возраст всегда будет целым, чтобы дробная часть не смущала, можно привести все значения к целочисленному типу. # In[37]: int(25.0) # int - от integer # Вообще функции для изменения типа переменных называются так же, как и сами типы или их сокращенные названия. # In[38]: float(23) # In[39]: str(2) # str - от string # In[40]: int("23") # Однако, если преобразование невозможно, Python выдаст ошибку (а точнее, исключение): # In[41]: float('23,56') # Так как запятая не воспринимается как десятичный разделитель в Python (в качестве разделителя используется точка), превратить строку '23,56' в число не получится, нужно будет сначала заменить запятую на точку. Как работать со строками, мы обсудим позже, но если интересно, можно сделать следующее: создать любую строковую переменную, а потом после ее названия поставить точку и нажать *Tab*. Так же, как и в случае с модулем *math*, выпадет список всех возможных методов, которые можно применять к строке. # In[42]: words = "political science" # In[43]: words.capitalize() # например, метод capitalize # In[44]: help(words.capitalize) # информация по нему