Введение в Python и обработку данных

Спецкурс кафедры Теоретической информатики мехмата МГУ

Подробная информация по курсу: http://rmbk.me/mm_python/

Итак, если вы видите этот файл, то вероятно вы правильно установили Jupyter Notebook, поздравляю.


Jupyter Notebook

Сначала про данный инструмент: Jupyter Notebook позволяет работать с Python в интерактивном режиме, является удобной обёрткой над IPython (Interactive Python).

Такие файлы, как этот, называются ноутбуками (от англ. notebook — блокнот, записная книжка) и имеют расщирение .ipynb. Они состоят из ячеек — Cell'ов, которые могут быть кодом на Python или текстом в формате Markdown (подробнее про формат здесь) с поддержкой формул LaTeX в знаках $ (к примеру, $sin(x) = 0$). Если ячейка с кодом, то ее можно запустить и сразу увидеть результат.

Попробуйте нажать на следующую ячейку с кодом и запустить ее. Запуск можно осуществить через панель вверху (кнопка Run), либо сочетанием Ctrl+Enter. Есть еще удобное сочетание Shift+Enter, которое запускает выделенную ячейку и переходит к следующей.

In [ ]:
print('Hello World!')

Ноутбуки запускаются над интерпретатором Python, который называется Kernel. В правом верхнем углу должны видеть слово Python 3 — это и есть его обозначение. Во вкладке Kernel (вверху в середине) процесс Python можно остановить и перезапустить.

Заметка: существуют Kernel'ы и для других языков: R, Julia, Scala.

У IPython есть дополнительные возможности, но останавливаться на них подробно не будем, и если всплывут в курсе — напомню про них. Справку по ним можно получить, выполнив следующую ячейку (да, у них особенный синтаксис, начинающийся с %):

In [ ]:
# %quickref

Из полезных фишек можно отметить %%timeit, который прогоняет код в ячейке много раз и выдает среднее время выполнения.

In [ ]:
%%timeit

# Пример кода, который выполняется не совсем мгновенно
def fibonacci(n):
    if n <= 0:
        return 0
    
    x, y = 0, 1
    for _ in range(1, n):
        x, y = y, x + y
    return y
    
fibonacci_numbers = [fibonacci(i) for i in range(3500)]

Python: основы основ

История

Версии Python:

  • Python 1.0 — январь 1994 года
  • Python 2.0 — 16 октября 2000 года
    • Python 2.7 — 3 июля 2010 года
  • Python 3.0 — 3 декабря 2008 года
    • Python 3.7 — 27 июня 2018 года

Мы будем изучать Python 3.

Почему Python?

Плюсы:

  • Python прост в понимании и освоении: структура, синтаксис, читабельность
  • При своей простоте — очень функционален
  • Мощное сообщество: Python используется практически везде
  • Множество сторонних библиотек и удобство их использования

Минусы:

  • медленный
  • не всегда подходит для крупных проектов

The Zen of Python:

In [ ]:
import this

Про сам Python

Pythonинтерпретируемый язык с динамической типизацией.

Есть разные реализации интерпретаторов: CPython (каноническая реализация на языке C), Jython, PyPy.

Объекты

В Python всё является объектами. Каждый объект обладает тремя следующими пунктами:

  • identity — сущность: аналог адреса в памяти компьютера
  • type — тип: описание объекта, его методы, члены и прочее
  • value — значение: конкретная "внутренность" объекта

К примеру, когда мы пишем строку 'Hello World!', то мы создаем экземпляр (instance) типа str со значением 'Hello World!'.

Сущность и тип объекта поменять нельзя. Если мы не можем поменять и значение объекта, то такие объекты называются immutable (неизменяемыми), а иначе mutable (изменяемыми).

Например, строки являются неизменяемым типом данных в Python. Т.е. если мы прибавим к строке другую в Python, то мы получим новый объект строки, в который были откопированы эти две, а не изначальную строку, к которой добавили вторую.

У каждого объекта в Python также есть счётчик ссылок (reference count). Этот счётчик увеличивается, если на объект начал ссылаться другой. Когда количество ссылок на объект становится равным 0, то это является сигналом для сборщика мусора (garbage collector) и объект рано или поздно будет удален из памяти интерпретатора.

Например, когда мы определяем локальную переменную в функции, а потом выходим из нее, то эту переменную уже "никак не достать", счетчик ссылок на нее будет 0 и она будет вскоре удалена.

Эта часть тяжела для понимания в начале пути изучения Python, вернитесь к ней через какое-то время.

Основные типы в Python

In [ ]:
print(type('Hello World!'))  # Тип str: string (рус. строка)
print(type(42))              # Тип int: integer (рус. целое число)
print(type(3.1415))          # Тип float: floating-point number (рус. число с плавающей запятой)
print(type(True))            # Тип bool: boolean (рус. булев тип, логический тип): True или False
print(type(None))            # Тип NoneType: означает отсутствие чего-либо, некий нейтральный элемент
In [ ]:
# Символом `#` в Python обозначаются комментарии в коде
# После этого символа можно писать любые знаки, интерпретатор пропустит их
# Комментарии нужны для дополнительного описания того, что происходит в коде

Объявление переменных

Имя переменной составляется из латинских букв, цифр и знаков _, которое должно начинаться не с цифры. Согласно PEP8 рекомендуется называть переменные буквами нижнего регистра и разделять слова нижним подчеркиванием.

Python — язык с динамической типизацией. Это значит тип переменной определяется в момент присваивания, а не в момент объявления. Т.е. мы можем присвоить переменной одного типа значение другого типа во время исполнения.

In [ ]:
a = 'Hello World!'
b = 42
pi = 3.1415
c = True
d = None

long_long_name = 'ABCDEF'
another_long_name = False

Основные операции

Числа

Приоритет операций как в математике, можно использовать скобки.

Заметка: Для целых чисел в Python предусмотрена длинная арифметика. Если в языке C int находится в пределах [-2147483648, 2147483647], то Python автоматически расширяет этот диапазон.

In [ ]:
print(10 + 15)      # Сложение
print(12 - 5)       # Вычитание
print(2 * 2)        # Умножение
print(5 / 2)        # Деление
print(5 // 2)       # Деление в целых числах
print(5 % 2)        # Остаток от деления
print(3.1415 ** 2)  # Возведение в степень

print((6 * 2 - 4) // 2)  # Комбинация операций

Строки

Строки можно объявлять с помощью парных одинарных или парных двойных кавычек. Между ними нет разницы, но стоит придерживаться единого стиля. К примеру, я больше люблю использовать одинарные.

In [1]:
str_1 = 'Hello'
str_2 = "World"

print(str_1 + ' ' + str_2)  # Сложение строк даёт новую строку составленную из указанных
print(str_1 * 5)            # Умножение строки на целое число дублирует ее в указанное количество раз

a = 'London is the capital of Great Britain'

# Получение информации о строке
print(a.count('a'))            # Количество вхождений буквы 'a' в строку
print(a.startswith('London'))  # Проверка на начало строки
print(a.isdigit())             # Проверка число ли в строке

# Получение другой строки
print(a.lower())              # Нижний регистр
print(a.upper())              # Верхний регистр
print(a.title())              # Каждое слово с большой буквы
print(a.replace('on', 'ON'))  # Замена 'on' в строке на 'ON'

# help(str)
Hello World
HelloHelloHelloHelloHello

Форматирование строк

А еще строки можно собирать из разных переменных. Эта возможность часто нужна для удобного вывода информации.

Полный список возможностей с примерами: pyformat.info

In [2]:
count = 15
value = 1.8

# Стандартный способ через `.format`
# Переменные пишутся в строке как `{}`, а `.format` подставляет их по очереди
# Эту очередь можно поменять при необходимости как во втором примере
print('Функция format: N = {}, X = {}'.format(count, value))
print('Функция format: X = {1}, N = {0}'.format(count, value))

# Новый с версии 3.6 способ задавать форматирование через f-строки
# В начале строки указывается буква `f`, а внутри фигурных скобок сразу название переменной
print(f'Через f-строки: N = {count}, X = {value}')

# Оба варианты актуальны в Python 3, использовать можно то, что удобнее
# Со времен Python 2 осталась возможность форматирования через знак `%`, но так уже мало кто делает
Функция format: N = 15, X = 1.8
Функция format: X = 1.8, N = 15
Через f-строки: N = 15, X = 1.8

Операторы сравнения

In [ ]:
a = 1
b = 42
c = 'Hello'

print('-- Числа:')
print(a == 1)  # Равно
print(3 != 5)  # Не равно
print(a < b)   # Меньше
print(a > b)   # Больше
print(a <= 1)  # Меньше, либо равно
print(a >= 1)  # Больше, либо равно

# Сравнение строк происходит лексикографически, т.е. символы сравниваются по-очередно
print('-- Строки:')
print(c == 'Hello')       # Равно, т.е. все символы совпадают
print(c != 'HelloWorld')  # Не равно, т.е. хотя бы один символ не совпал
print('abc' < 'cde')      # Меньше, т.е. каждая i-ая буква первой строки 
                          # идет в алфавите раньше i-ой буквы второй строки

Некоторые типы можно приводить к другим

Делается это указанием целевого типа от желаемого объекта:

In [ ]:
# Получить из строки число: int('42')
a = int('42')
print(a, type(a))

# Или наоборот из числа сделать строку: str(125)
b = str(125)
print(b, type(b))

Функции

Функция это блок кода, который можно вызывать из других мест. Блоки кода оформляются сдвигом в 4 пробела.

def НАЗВАНИЕ_ФУНКЦИИ(АРГУМЕНТЫ_ФУНКЦИИ):
    ТЕЛО_ФУНКЦИИ

Ключевое слово return обозначает, что должна вернуть функция как свой ответ. Функции могут быть без return, тогда они автоматически вернуть None после выполнения.

In [ ]:
def f(a, b):
    return a + b

def g():
    print('Hello!')

print(f(1, 2))

Условия

Оформляются также со сдвигом в 4 пробела

if УСЛОВИЕ:
    БЛОК_КОДА_ЕСЛИ_УСЛОВИЕ_ИСТИННО
else:
    БЛОК_КОДА_ЕСЛИ_УСЛОВИЕ_ЛОЖНО
In [ ]:
def f(a):
    if a < 10:
        print(f'{a} меньше 10')
    elif a > 20:  # Сокращение для else if
        print(f'{a} больше 20')
    else:
        print(f'{a} между 10 и 20')

f(4)
f(16)
f(25)

Циклы

Циклы используются для многократного повторения похожих инструкций.

while УСЛОВИЕ_ПОВТОРЕНИЯ_ЦИКЛА:
    ТЕЛО_ЦИКЛА

    if УСЛОВИЕ_ПРОПУСКА_ОСТАВШЕЙСЯ_ИТЕРАЦИИ:
        continue

    if УСЛОВИЕ_ВЫХОДА_ИЗ ЦИКЛА:
        break
In [ ]:
i = 1           # Инициализируем переменную i, она будет нашим счетчиком
while i <= 5:   # Ставим условие на i: она должна быть меньше, либо равна 5 
    print(i)    # Печатаем номер текущей итерации i
    i += 1      # Прибавляем к i единичку, т.к. итерация подошла к концу
    
# `+=` это сокращение для i = i + 1
In [ ]:
i = 0
while True:  # Бесконечный цикл
    i += 1
    
    if i > 10:
        break  # Выходим из цикла, когда i станет больше 10
    
    if i % 2 == 0:        
        continue  # Пропускаем четные числа
        
    print(i, i * i)  # Печатаем i и его квадрат

Т.к. счетчики нужны почти всегда, то Python предоставляет для этого генератор range (подробнее про генераторы будет в следующих лекциях). Он используется в двух вариациях.

In [ ]:
# help(range)

n = 4

# Выдает числа от 0 до n-1
for i in range(n):
    print(f'Первый цикл: {i}')

start = 10
stop = 50
step = 15

# Выдает числа от start до stop-1 с шагом step
for i in range(start, stop, step):
    print(f'Второй цикл: {i}')

Модули

Некоторые функции и переменные нужны только в особых случаях и нет надобности постоянно хранить их в памяти. Поэтому в Python предусмотрена система модулей. Каждый модуль отвечает за какую-то область требований.

import НАЗВАНИЕ_МОДУЛЯ
# или
from НАЗВАНИЕ_МОДУЛЯ import КОНКРЕТНЫЕ_ЭЛЕМЕНТЫ_МОДУЛЯ

Примеры обоих подходов ниже:

In [ ]:
import math

# help(math)
# help(math.sin)

print(math.sin(math.pi / 2))
In [ ]:
from math import sin, pi

# help(sin)

print(sin(pi / 2))

Работа с операционной системой

Ввод с клавиатуры

In [ ]:
# help(input)

a = input()
n = input('Введите N: ')
print(a, n)

Работа с файлами: запись

In [ ]:
# help(open)

my_string = 'London is the capital of Great Britain'

# Открываем файл 'a.txt' на запись в папке, в которой запущен ноутбук
with open('a.txt', 'w') as file:
    file.write(my_string)

Работа с файлами: чтение

In [ ]:
# Открываем файл 'a.txt' на чтение в папке, в которой запущен ноутбук
with open('a.txt', 'r') as file:
    my_string = file.read()

print(my_string)

Задачи и решения

  1. Пользователь вводит радиус шара R. Вывести площадь поверхности и объём шара.
In [ ]:
from math import pi

def request_radius():
    r = input('Введите число R: ')
    if not r.isdigit():
        return None
    return int(r)

def square(r):
    return 4 * pi * r ** 2
    
def volume(r):
    return (4 / 3) * pi * r ** 3

r = request_radius()
if r is None:
    print('Радиус должен быть числом!')
else:
    print(f'Площадь поверхности шара: {square(r)}')
    print(f'Объем шара: {volume(r)}')
  1. Задача DNA на Rosalind
In [ ]:
with open('rosalind_dna.txt', 'r') as file:
    dna = file.read()
    
print(dna.count('A'), dna.count('C'), dna.count('G'), dna.count('T'))

Дополнительные материалы

Число с плавающей запятой

Или почему в компьютере 10 / 3 = 3.3333333333333335

Краткий ответ: в процессоре невозможно реализовать бесконечно точные вычисления, с какого-то момента приходится урезать точность. Подробнее про представление вещественных чисел в памяти можно почитать по ссылкам: Википедия, Хабр, вики ИТМО.

PEP — Python Enhancement Proposals

Дословно — предложения по улучшению Python. Это документ со стандартизированным дизайном, предоставляющий общую информацию о языке Python, включая новые предложения, описания и разъяснения возможностей языка. Предложения нумеруются, некоторые отклоняются, некоторые приняты давным давно.

Полный список предложений: python.org/dev/peps, некоторые из них:

  • PEP8: Style Guide for Python Code — рекомендации как писать код, чтоб его могли читать не только вы сами
  • PEP3000: Python 3000 — PEP от Гвидо ван Россума, который положил начало развития Python 3.0

Disclaimer

Этот ноутбук будет расширяться и исправляться. Пожелания или найденные ошибки сообщайте по координатам в самом начале документа.

Успехов в изучении Python!