Как правило, первая программа которую пишут на языке - это "Hello world!". Ниже приведен полный код этой программы на языке Python 3.
print("Hello world!")
Здесь, мы первый раз сталкиваемся с функцией print
, это функция вывода. В простейшем случае, чтобы написать что-нибудь на экран нам достаточно написать print()
и внутри скобочек, то что мы хотим вывести.
print(10)
print(2 + 2)
print(11, 11)
print("Hi!", 42, 12.5)
Конечно, как в любом языке программирования, в Python есть переменные. Самое первое, что мы научимся делать -- это присваивать переменной значение. Ниже показано, как это сделать.
a = 5
b = 7 + 3
print("a + b =", a + b)
c = a + b
print('c =', c) #строки так же можно задавать в одинарный кавычках, "abc" и 'abc' это одно и то же
В этом куске кода выше есть как минимум одна новая вещь: комментарий, он начинается с символа #
и продолжается до конца строки.
some_string = "string variable"
print("some_string =", some_string)
Как вы заметили, в отличие от С/С++, Pascal мы при объявлении переменной не задавали ее тип. Все очень просто в Python у переменной нет типа, подобное свойство языка называют динамической типизацией.
Пример ниже демонстрирует это свойство чуть-чуть подробнее.
a = 5
print(a)
a = "A is string now!"
print(a)
Подобное бывает очень удобно, но вынуждает отдельно следить за тем, какой тип у значения этой переменной. Например "5" и 5, это разные вещи. Одно строка, второе целое число.
Давайте научимся складывать, умножать, вычитать и производить другие операции с целыми или вещественными числами. Стоит понимать, что целое число и вещественное число это совсем разные вещи для компьютера.
Список основных арифметических действий, которые вам понадобятся:
a = 1
b = 2
print(a + b)
a = 2.0
b = 1
print(a + b)
a = 4
b = 5
print(a - b)
a = 3.0
b = 4
print(a - b)
a = 2
b = 4
print(a * b)
a = 2.1
b = 4
print(a * b)
a = -2.1
b = 4
print(a * b)
a = 10
b = 2
print(a // b)
a = 10
b = 3
print(a // b)
a = -10
b = 3
print(a // b)
a = 10
b = 3
print(a / b)
a = 10
b = 2
print(a / b)
a = 10
b = 2
print(a % b)
a = 10
b = 3
print(a % b)
a = 10
b = 3.5
print(a % b)
a = -10
b = 3
print(a % b)
a = 2
b = 2
print(a ** b)
a = -2
b = 2
print(a ** b)
a = 2
b = -2
print(a ** b)
a = 2.5
b = 2
print(a ** b)
a = 4
b = 0.5
print(a ** b)
a = 4
b = 0.5
print(a ** b)
a = -4
b = 0.5
print(a ** b)
a = -4.2
b = -0.5
print(a ** b)
Так же существует специальный операторы позволяющие сократить записи вида: a = a + 5. Все эти операторы записываются как "оператор=", ниже несколько примеров.
a = 1
a += 2 #эквивалент а = а + 2
print(a)
a = 3
b = 2
a *= b #эквивалент а = а * b
print(a)
a = 3
b = 2
a **= b #эквивалент а = а ** b
print(a)
Думаю, всем понятно, как работает оператор if, ниже несколько примеров, чтобы разобраться с синтаксисом python.
if 5 < 3:
print("Правда")
else:
print("Ложь")
if 9 * 7**2 > 8 * 5**2:
print("Правда")
else:
print("Ложь")
if True:
print("Ветка if")
else:
print("Ветка else")
if False:
print("Ветка if")
else:
print("Ветка else")
if False:
print("Ветка if")
elif True:
print("Ветка elif")
else:
print("Ветка else")
Понятно, что после if может стоять не только значение True или False. Посмотрим, что делает Python, если после if стоит нечто более странное?
if 0:
print("Ветка if")
else:
print("Ветка else")
if 5:
print("Ветка if")
else:
print("Ветка else")
if -1:
print("Ветка if")
else:
print("Ветка else")
if "":
print("Ветка if")
else:
print("Ветка else")
if "abc":
print("Ветка if")
else:
print("Ветка else")
if []:
print("Ветка if")
else:
print("Ветка else")
if [2, 3, 4]:
print("Ветка if")
else:
print("Ветка else")
Посмотрим, как устроены логические операции и операции сравнения в Python.
Вот список тех из них, которыми вы будете пользоваться наиболее часто:
Рассмотрим несколько примеров.
print(5 > 2)
print(not 5 > 2)
a = 5
b = 2
print(a > b and a >= b)
a = 5
b = 2
print(True and a > 2)
a = 5
b = 2
print(False or b >= 2)
a = 5
b = 2
print(b == a)
a = 5
b = 2
print(b != a)
Напоследок несколько специфичных вариантов.
print("abc" and [1, 2, 34])
print("abc" < [1, 2])
print("abc" == [1, 2])
print("abc" != [1, 2])
Конечно, в условии после if
чаще всего и приходится использовать логические операции. В качестве примера, давайте напишем программу, проверяющую является ли данный год високосным.
year = 2015
if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
print("YES")
else:
print("NO")
Единственная проблема у кода выше - это невозможность считать год с клавиатуры, как можно заметить, мы задали его в явном виде. Для решения этой проблемы нам понадобится функция input
, она считывает строчку (до перевода строки) из stdin
(стандартного потока ввода, который обычно связан с клавиатурой). Также нам понадобится функция int
, она преобразует число записанное в виде строки в число.
year = int(input())
if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
print("YES")
else:
print("NO")
Самый просто устроенный цикл - while
. Он работает точно так же как и в остальных языках программирования.
i = 0
while i < 5:
i += 1
print(i)
Естественно, после while
может стоять любое условие.
Также есть оператор break
, он заканчивает выполнение цикла.
i = 0
while True:
print("before", i)
if i == 2:
break
print("after", i)
i += 1
Для примера давайте напишем программу, которая выводит наименьшую степень двойки, которая больше заданного числа $n$.
n = int(input())
cp, i = 1, 0
while n >= cp:
cp *= 2
i += 1
print("cp = %d, i = %d" % (cp, i)) #это более удобный способ форматирования строк, ниже несколько комментариев про него
В задаче выше мы воспользовались несколькими новыми вещами.
Во-первых, конструкция вида a, b = c, d
, называются параллельным присваиванием. В этом случае переменной a
будет присвоено значение c
, а переменной b
значение d
. В некоторых ситуациях это бывает очень удобно.
Во-вторых, если нам нужно получить строку, содержащую несколько целых чисел с некоторым форматированием, то это можно сделать с помощью конструкции подобной конструкции выше. Формальное объяснение этой конструкции достаточно громоздко, давайте посмотрим на несколько примеров.
print("I'am %d years old." % 19)
print("2 * 2 = %d" % (2 * 2)) #самый простой пример просто вставляющий целое число в нужное место
print("%02d:%02d" % (15, 2)) # немного форматирования самого числа
Несколько общих слов. List это некоторое подобие массива в "привычных" вам языках программирования лишь с тем отличием, что в list
могут храниться элементы разных типов. Давайте попробуем разобраться на примерах.
a = [1, 2, "Hi"] #мы создали список и присвоили переменной а этот список
print(a[0], a[1], a[2]) #так обращаться к элементам списка, элементы индексируются с нуля
b = list() #таким образом можно создать пустой список
В Python есть отрицательная индексация. $-1$ элемент это последний элемент, $-2$ элемент это предпоследний элемент списка и так далее. После примеров ниже должно стать совсем понятно.
a = [1, 2, "Hi"]
print(a[-2])
b = ["a", 1, 2, 3, 4, "b", -10, [1, 2, 3], 3.4, "!!!"] #элементом списка может быть список
print(b[-3])
a = [1, 2, "Hi"]
a[1] = 4 #можно изменить отдельный элемент
print(a) #можно вывести весь список, но он это делается в неудобном формате
Бывает такое, что нам нужна только некоторая часть списка, например все элементы с $5$ по $10$, или все элементы с четными индексами. Подобное можно сделать с помощью срезов.
Срез задается одним из нескольких способов:
Нужно понимать, что любой из параметров может быть опущен так, например, срез a[::] будет содержать просто весь список a.
print([1, 2, 3, 4, 5, 6, 7, 8][:5])
print([1, 2, 3, 4, 5, 6, 7, 8][1:7:2])
print([1, 2, 3, 4, 5, 6, 7, 8][:0])
print([1, 2, 3, 4, 5, 6, 7, 8][::2])
print([1, 2, 3, 4, 5, 6, 7, 8][::-1])
print([1, 2, 3, 4, 5, 6, 7, 8][2::-1])
Давайте немного подробнее поговорим о присваивании списков, с этим в Python есть несколько сложностей.
Как уже было сказано ранее, Python интерпретируемый язык. Во время выполнения, все данные которые у вас есть в программе он должен хранить, поэтому у интерпритатора во время выполнения хранится множество существующих объектов, и переменная это всего лишь ссылка на объект, который хранит интепритатор.
Давайте чуть-чуть подробнее изучим, как устроен лист с учетом ссылочного устройства.
a = [1, 2, 3, 4] #а - ссылка на лист, каждый элемент листа это ссылка на элементы 1, 2, 3, 4
b = a #b - ссылка теперь на тот же лист
print("id(a) = %d, id(b) = %d" % (id(a), id(b))) #в Python у каждого объекта есть свой id, это неокторое уничкальное число сопоставленное объекту
a[0] = -1
print("b =", b)
Также для списка есть набор удобных функций уже встроенных в Python, которые иногда упрощают жизнь. Давайте посмотрим на некоторые из них.
l = [1, 2, -1, 3, 2, -2, 1, 5, 7, 3]
print(min(l))
#не стоит думать, что min можно брать только от list или tuple, конечно, существует min от двух элементов
print(min(12, 10))
print(sum([2, 3, 11, 1])) #эта функция суммирует все числа в list или tuple
l = [1, 2, 3]
l.append(4) #метод append добавляет элемент в конец списка
print(l)
l.pop() #метод pop удаляет из списка последний элемент
print(l)
l = [1, 2, -1, 3, 2, -2, 1, 5, 7, 3]
print(l.index(3)) #заметьте, что в списке l у нас две тройки и index возвращает индекс первой из них
l = [1, 2, -1, 3, 2, -2, 1, 5, 7, 3]
print(l.index(115)) #если элемента нет в списке, то произойдет ошибка выполнения
Так же есть удобный метод sort
, она сортирует список по невозрастанию.
a = [3, 2, 4, 1, 2]
a.sort()
print(a)
Еще одна приятная функция это reverse
, она, как следует из названия, переворачивает список.
a = [1, 4, 2, 5, 2]
a.reverse()
print(a)
Tuple почти ничем не отличает от list
, только он неизменяемый. То есть нельзя взять и изменить один элемент. Во всем остальном они буду идентичны.
a = (1, 2, "Hi") #tuple записывается в круглых скобках
print(a[0], a[1], a[2])
b = tuple() #изменения по сравнению с аналогичным куском кода для списка минимальны
a = (1, 2, "Hi")
a[1] = 4 #так делать нельзя, о чем интерпретатор нам скажет
a = (1, 2, "Hi")
a.sort() #аналогично нельзя, ведь sort хотел бы изменить a
Tuple так же умеет работать с срезами.
Выше мы встречались с такой конструкцией как параллельное присваивание. Давайте ее немного обобщим.
Раньше у нас параллельное присваивание выглядело так:
a, b = c, d
Но! Если мы вместо двух значений c
и d
поставим один tuple
или list
содержащий столько же элементов, сколько и переменных в левой части равенства, то Python проделает аналогичное параллельное присваивание.
a, b = (1, 2) #самый простой случай, когда мы присваиваем в явном виде заданный tuple
print(a, b)
a, b, c = [2, "abs", 3] #то же самое но со списком
print(a, b, c)
tup = (1, 2, 3)
a, b, c = tup #чуть менее тривиальная запись того же самого
print(a, b, c)
Впереди нас ждет еще один кусочек про параллельное присваивание, а пока остановимся.
Цикл for
имеет в Python свою специфику.
В нашем случае цикл имеет один из двух видов:
for
переменная in list
/tuple
for
переменная in range(start, end, step)
Рассмотрим примеры.
for i in (2, 3, 5):
print(i)
t = [3, "ads", 4]
for i in t:
print(i)
for i in range(5):
print(i)
for i in range(2, 5):
print(i)
for i in range(2, 10, 3):
print(i)
Стоить заметить, что поведение параметров range
очень похоже на поведение параметров у срезов.
Примеры ниже либо сводят с ума либо показывают, что range
во многом похож на list
! Но чтобы работали эти примеры нужен Python 3.3 или более новой версии.
r = range(5)
print(r[2], r[-1])
Аналогично циклу while
для цикла for
есть оператор break
.
for i in range(10):
print("before", i)
if i == 2:
break
print("after", i)
В Python у цикла for
есть возможность написать ветку else
. Это будет работать так:
если цикл был завершен при помощи break
, то ветка else
выполнена не будет, в противном случае, после выполнения цикла она будет выполнена.
Достаточно странная возможность, чтобы понять как это можно использовать, решим задачу. Дан список, нужно проверить встречается ли в нем $-1$, если встречается, вывести "YES", иначе "NO". (Мы еще не умеем считывать целиком список, поэтому пока зададим его в коде программы.)
l = [1, 2, 3, 4, 5, 10, 1, 5, -1, 10, 12]
for i in l:
if i == -1:
print("YES")
break
else:
print("NO")
l = [1, 2, 3, 4, 5, 10, 1, 5, 10, 12]
for i in l:
if i == -1:
print("YES")
break
else:
print("NO")
Такая реализация иногда заметно проще, чем заводить отдельную переменную для флага или писать if...else
Мы уже раньше много раз встречались со строками, задавая их, как правило в явном виде в кавычках. Даже много чего делали с ними: выводили, даже чуть-чуть форматировали. Давайте подробнее обсудим, что можно делать со строками средствами Python.
a = "abc"
b = "edf"
print(a) #просто вывести
print(a * 2) #строки можно естественным образом умножать на целое число
print(a + b) #строки можно складывать
print(a[0], a[-1]) #можно обращаться к элементам строки
a = "abc"
a[0] = 'f' #строки неизменяемые как и tuple
a = 124 #число
b = str(a) #можно число преобразовать в строчку
print(a, type(a))
print(b, type(b))
Выше мы использовали функцию type
, с ее помощью очень удобно узнавать тип какой-либо переменной. Она вряд ли вам понадобится на контесте, но иногда может пригодиться для целей отладки.
a = int("1234")
print(a, type(a)) #помните строчку int(input()), там нет никакой магии, мы просто преобразовывали строку к числу
a = input()
print(a, type(a)) #функция input просто считывает строчку до перевода строки, все очень просто
Как было сказано выше, строки неизменяемые, но достаточно часто встречается ситуация, когда нам нужно изменить один символ в строке. В таких случаях преобразуют строку к списку и получают список символов, то есть строк состоящих из одного символа, изменяют один элемент списка, что мы уже научились делать, а потом список строк склеивают в одну большую строку. Давайте подробнее посмотрим, как все это делается.
a = "long string" #у нас есть строка, мы хотим уметь ее изменять
print(a)
l = list(a) #сделаем из строки список символов
print(l)
l[2] = "!" #изменим один элемент списка
print(l)
В предыдущем кусочке мы научились преобразовывать строку к списку символов и изменять один символ. Теперь нам нужно научиться из списка символов делать одну большую строку.
Для этого в Python у строки есть метод join
.
s.join(l)
- вернет строку, в которой все элементы списка $l$ записаны через разделитель(строку) $s$.
print("#".join(["1", "2", "3"])) #запишет "1" "2" "3" через разделительную строку "#"
print("".join(["1", "2", "3"])) #запишет "1" "2" "3" через пустую разделительную строку
Способом выше как раз и делается, что нам нужно. Давайте теперь целиком напишем программу, которая меняет в считанной строке второй элемент на символ "!".
s = input()
l = list(s)
l[1] = "!" #первый символ имеет индекс 0, второй символ имеет индекс 1
s = "".join(l)
print(s)
Так же пока мы не умеем выводить список строк через пробел, это так же делается с помощью метода join
.
Есть метод противоположный методу join
- это split
, он разбивает строку по разделяющей строке и возвращает список строк.
print("1#2#3".split("#")) #разобьет строку по символу "#"
print("1 2 3 fasd".split()) #split без параметров разбивает строку по пробельным символам
print("1abc2abcd3".split("abc")) #строка разделитель может стоять более чем из одной буквы
Иногда возникает необходимость создать список с определенными значениями элементов. Например, предподсчитать квадраты чисел или получить список вида [1, 2, 3, 4, 5, 6, ...]
, или даже просто получить список заполненный нулями.
Самый простой способ это с помощью метода append
добавлять в конец списка нужные элементы, например как сделано в коде ниже.
l = list()
for i in range(10):
l.append(i**2)
print(l)
Конечно, в Python существует более простой способ делать подобные вещи, он называется генератор списка. Для понимания его можно рассматривать как сокращение записи с for
, но, формально, он сокращением не является, это просто отдельная конструкция.
l = [i**2 for i in range(10)]
print(l) #этот код делает то же самое, что и код выше
Как можно попытаться запомнить конструкцию:
имя_списка = [то_что_будет добавляться в конец for переменная in что-то]
l = [0 for i in range(10)] #список длины 10 из нулей
print(l)
l1 = [0] * 10 #списки можно как и строки умножать на число, но этот способ имеет свои особенности, лучше генератор
print(l1)
l = [2**i for i in range(10)] #список длины 10 из степеней двоек
print(l)
На самом деле генераторы умеют "сокращать" еще более сложную запись. Посмотрим на пример ниже.
l = list()
for i in range(10):
if i % 2 == 1:
l.append(i**2)
print(l) #в l квадраты нечетных чисел
l = [i**2 for i in range(10) if i % 2 == 1]
print(l)
В конце генератора можно написать условие, при выполнении которого элементы будут добавляться.
Как вы могли заметить, мы так и не научились считывать два числа из одной строки. Это одна из немногих вещей, которая в Python чуть-чуть сложнее, чем в более привычных языках. Сейчас нам понадобится все, что мы изучили выше.
a, b = [int(i) for i in input().split()] #так считываются 2 целых числа из одной строки
print(a, type(a))
print(b, type(b))
Что происходит при выполнении этого кода:
input
и считывается одно строка.split
и разбивает ее по пробелам. Наши числа как раз и были записаны через пробел.split
вернули список строк, после этого цикл в генераторе списка начинает работать и перебирать элементы.int
.a
присваивается значение первого числа в строк, переменной b
значение второго числа.Давайте ниже напишем эквивалент этого кода, только без генератора списка. Так писать не нужно, потому что это медленно и на самом деле сложнее.
s = input()
l = s.split()
print(l) #посмотрим, что получилось
ans = list()
for el in l:
ans.append(int(el))
print(el)
a, b = ans
print(a, type(a))
print(b, type(b))
Как вы можете заметить, этот код делает ровно тоже самое, просто мы все написали длиннее.
Заметим, что ровно таким же способов из строки считывается сколько угодно чисел. Чтобы окончательно разобраться, давайте решим задачу. На вход программе дается строка^ содержащая несколько чисел через пробелы, нужно найти минимум из этих чисел.
l = [int(i) for i in input().split()]
print(min(l))
На самом деле все то же самое можно было написать в одну строчку!
print(min([int(i) for i in input().split()]))
Чтобы понять, как выводить список через пробел, напишем программу, которая считывает набор чисел из одной строки и сортирует их по убыванию.
Метод join
требует на вход список строк, именно для этого мы и воспользовались генератором. То есть генератор здесь только для того, чтобы преобразовать список чисел в список строк. Посмотрите, это действительно так.
На самом деле, мы уже умеем почти все, что нужно чтобы писать простые программы на Python. Для дополнительного удобства, давайте подробнее рассмотрим функцию print
, мы много раз ей пользовались, но подробно не говорили.
На самом деле нам хватает уже того, что мы умеем, разве что иногда хочется выводить числа не через пробел или не делать перевод строки после каждого вызова print
. Это делается с помощью параметров sep
и end
. sep
это строка, которую print
вставляет между двумя элементами для вывода, по умолчанию пробел, а end
это строка, которая записывает в конце после вызова print
, по умолчанию это '\n', то есть перевод строки.
Посмотрим на несколько примеров.
print(12, 12, sep=":", end="")
print(1, 2, 3, sep=", ", end="!")#sep и end могут быть не односимвольными
Кажется, на этом хватит :)