Вы находитесь на странице: 1из 89

Знакомство со средой

Аннотация
Первый урок посвящен введению в язык Python и знакомству с теми техническими
средствами, которые понадобятся нам для обучения.
Сегодня мы научимся писать программы, которые умеют что-то выводить на
экран и считывать информацию с клавиатуры. И познакомимся с переменными.

Введение
Программа — список команд, то есть инструкций для компьютера:

 отобразить что-нибудь на экране,


 вычислить что-нибудь
и т. д.
В вашем компьютере много разных программ. Программа-браузер показывает вам
страницы в Интернете, программа-плеер проигрывает музыку, Word позволяет
редактировать тексты, игры развлекают вас, вирусы мешают — и все это программы.
Чтобы создать страницу на сайте в Интернете, которую получит и покажет ваш браузер
(например, вашу страничку «ВКонтакте» или результаты поиска в Яндексе),
компьютер, на котором работает этот сайт, часто тоже выполняет какую-то программу.
Есть разные способы записать программу. Однако наиболее удобная для компьютера
форма записи в виде машинного кода неудобна для человека. Поэтому для
составления программ придумали языки программирования.
Язык программирования
Язык программирования — набор строгих правил, согласно которым компьютер
может понимать команды и выполнять их. Текст программы, написанной на любом
языке программирования, называется программным кодом (или просто кодом).
Языки программирования бывают двух основных типов: компилируемые и
интерпретируемые. Если программа написана на компилируемом языке (например,
Pascal или C++), перед ее выполнением нужно сначала полностью проверить на
некоторые ошибки и перевести в более понятную для компьютера форму. Это делает
специальная программа — компилятор.
Если программа написана на интерпретируемом языке (например, Java или Python),
она не переводится целиком в машинный код, а специальная программа —
интерпретатор — идет по коду, анализирует и выполняет каждую отдельную команду.
Такой подход придает языку особую гибкость и простоту в написании программ.
Язык Python, который мы сейчас начнем изучать, разработал голландский
программист Гвидо Ван Россум (Guido van Rossum) в 1991 году. Не подумайте, что язык
назван в честь змеи-питона: Гвидо был большим фанатом британского комедийного
сериала «Летающий цирк Монти Пайтона» (англ. Monty Python’s Flying Circus), и
именно оттуда пришло название языка. В настоящее время в русском языке для
обозначения используют два варианта — «Питон» и «Пайтон».
Python относится к интерпретируемым языкам программирования: чтобы запустить
написанную на Python программу, нужен интерпретатор Python (его можно скачать с
сайта python.org). Подробнее об установке языка Python смотрите в видеоинструкции к
уроку.

Знакомство с IDE
Команды для интерпретатора можно писать в обычном текстовом редакторе
(например, в «Блокноте»). Но чаще для этого пользуются специальной программой,
которая называется средой разработки (англ. IDE, Integrated Development
Environment). Среда разработки — тоже текстовый редактор, но с дополнительными
возможностями. Например, она умеет сама находить на компьютере программу-
интерпретатор и запускать одной кнопкой. Среда разработки, кроме того, форматирует
написанный вами код, чтобы его удобно было читать, а иногда даже подсказывает, где
вы допустили ошибку.
На первом этапе мы будем использовать среду разработки Wing IDE. Ее можно скачать
с сайта разработчика, фирмы Wingware. В будущем вам может потребоваться более
сложная и более богатая возможностями среда разработки. В этом случае мы
рекомендуем использовать PyCharm — продукт российской фирмы JetBrains.
Ну что же, пора приступать к разработке программ. Для начала запустите среду
разработки WingIDE. Давайте проверим настройки кодировок файлов. Эти настройки
потребуются для корректной сдачи программ в тестирующую систему.

 Зайдите в меню Edit → Preferences. Перейдите к категории Files. Для опции


Default Encoding выберите значение Unicode (UTF-8) utf-8.
 Зайдите в меню Edit → Preferences. Перейдите к категории Debugger → I/O. Для
опции Debug I/O Encoding выберите значение Unicode (UTF-8) utf-8.
Примечание: на компьютерах с системой Mac OS вместо меню Edit необходимо
открывать вкладку Wing 101 или Cmd + «,».
PEP 8
При оформлении программ мы будем пользоваться PEP 8 — Python Enhanced Proposal.
Это документ, описывающий общепринятый (рекомендуемый) стиль написания
программ на языке Python. Документ создан по рекомендациям Гвидо Ван Россума и
Барри Уорсо, ознакомиться с материалами на русском языке можно, например, тут. В
наших материалах мы будем отмечать рекомендации PEP 8 таким блоком.
Среды разработки могут помогать с форматированием по PEP 8. Для включения такой
возможности в Wing IDE зайдите в меню Edit → Preferences. Перейдите к категории
Editor → PEP 8. Для опции Auto-Reformat for PEP 8 выберите значение Lines After Edit.
Команда print()
А теперь изучим команду вывода на экран. Для вывода на экран используется команда
print().
Команда print()
Внутри круглых скобок через запятую мы указываем то, что необходимо вывести на
экран. Если это какой-то текст, указываем его внутри кавычек. Кавычки могут быть как
одинарными, так и двойными. Главное, чтобы текст начинался и заканчивался
кавычками одного типа. Команда print записывается только строчными буквами,
другое написание недопустимо, так как в Python строчные и заглавные буквы
различны.
Создайте в среде новый файл и напишите в нем команду вывода на экран слова
«Привет!» Команда будет выглядеть так:
print('Привет!')
Обратите внимание: слово print в Wing выделено голубым цветом, а слово «Привет!»
— фиолетовым. В среде Wing IDE используется цветовое выделение синтаксиса. Все
стандартные команды и функции выделяются синим и голубым цветом, фиолетовым
цветом выделяются текстовые данные — строки, заключенные в кавычки.
PEP 8
Избегайте использования пробелов cразу перед открывающей скобкой, после которой
начинается список аргументов функции.
Правильно:
print('Привет!')
Неправильно:
print ('Привет!')

Настало время запустить первую программу. Однако кнопка запуска Run пока
недоступна. Перед запуском необходимо сохранить файл на диск.
Вы будете писать много программ, только за первый год обучения их будет более 500,
поэтому для удобства создавайте для каждого урока свою папку, в которой будете
хранить программы этого урока, а сами файлы с программами называйте так, чтобы
было понятно, о какой задаче идет речь. Назовите данный файл hello и сохраните его.
Теперь стала доступна кнопка запуска. Запустите программу.

Тестирующая система
Вы только что написали свою первую программу. А сейчас вы сдадите свою первую
задачу в тестирующую систему.
Измените свою программу так, чтобы она решала задачу «Приветствие». Запустите и
проверьте ее. И, если она работает верно, сдавайте задание в тестирующую систему.
Не забудьте сохранить новую программу в отдельном файле. Сейчас это кажется не
очень важным, но потом, когда программ станет больше, а сами они длиннее и
сложнее, привычка систематизировать материалы очень вам поможет. Чтобы не
путаться, код какой программы в каком файле, именем может служить название
задачи в тестирующей системе.
Написать или запустить неверную программу — не страшно. Что-то не понять — тоже
не страшно. Даже опытные программисты иногда ошибаются и что-то не понимают.
Поэтому в случае затруднений всегда смело задавайте вопросы и просите
преподавателя вам помочь.
Ваша программа пока умеет только здороваться. Давайте сделаем так, чтобы она
выводила две строчки с текстом. В первой строке «Привет, Яндекс!», а на второй —
«Приятно познакомиться.». Для этого нам понадобится еще одна команда print. Эту
команду нам обязательно надо написать с новой строки. Каждая новая команда
пишется с новой строки! Сохраните программу с новым именем acquaintance,
запустите и проверьте. И, если все правильно, сдавайте сдавайте задачку
«Знакомство» в тестирующую систему.
Когда сдадите задачу, попробуйте внести в свою программу ошибки: добавьте
опечатку в слово print, уберите открывающую или закрывающую скобку, придумайте
еще что-нибудь необычное. Обратите внимание: в консоли появляется сообщение, в
котором есть слово Error. SyntaxError: invalid syntax часто означает именно
забытую кавычку или скобку. Проведите небольшой эксперимент: если вы добавите
опечатку в слово print, оно станет черным — редактор не узнает его и не понимает, что
это команда.
Давайте теперь немного изменим нашу последнюю программу. Попробуйте заменить
строчку print('Привет, Яндекс!') на строку print('Привет', 'Яндекс!').
Запустите и посмотрите, что будет выведено на экран. В этот раз мы внутри команды
print указали две строки, заключенные в кавычки, но разделили эти строки между
собой запятой. Как уже говорилось в начале урока, внутри круглых скобок через
запятую указывается то, что нужно вывести на экран. В данном случае на экран
выводятся две строки. Первая — «Привет», вторая — «Яндекс!» Эти строки пишутся в
команде print через запятую, а появляются на экране через пробел. То есть запятая
внутри команды заменяется на пробел при выводе на экран.
PEP 8
Обратите внимание: после запятой согласно стандарту PEP 8 обязательно нужно
добавлять пробел.
Правильно:
print('Привет', 'Яндекс!')
Неправильно:
print('Привет','Яндекс!')
Выполнив программу, мы видим, что фраза «Привет Яндекс!» не соответствует
требуемой. В ней не хватает запятой. Запятая должна быть выведена на экран, а это
значит, что она должна оказаться внутри строки, заключенной в кавычки. Исправьте
программу и добейтесь правильного вывода. Самостоятельно разбейте фразу
«Приятно познакомиться.» на две строки, которые внутри команды print будут
записываться через запятую.

Команда input()
Пока что все наши программы выводили на экран фразы, известные в момент
написания кода. Но программы могут работать и с данными, которые станут известны
только во время выполнения: например, их будет вводить пользователь с клавиатуры.
Мы можем реализовать это так:
print('Как тебя зовут?')name = input()print('Привет,', name)
Запустите эту программу. Она выводит на экран строчку «Как тебя зовут?» и дальше
ждет от пользователя ввода ответа на вопрос, ввода имени.
Введите имя. Запустите еще раз. Введите чужое имя.
Здесь используется команда input().
Команда input()
Она всегда пишется с круглыми скобками. Команда работает так: когда программа
доходит до места, где есть input(), она ждет, пока пользователь введет строку с
клавиатуры (ввод завершается нажатием клавиши Enter). Введенная строка
подставляется на место input().
То есть, если вы ввели «Аня», программа дальше будет работать так, как будто на
месте input() было написано «Аня».
Таким образом, input() получает от пользователя какие-то данные и в место вызова
подставляет строковое значение, в нашем случае записывает его в качестве значения
переменной name. Мы рассмотрим, что значит сохранить в значение переменной, а
пока запомните:
если нужно, чтобы программа что-то печатала на экране и это увидел пользователь, —
print. Если нужно, чтобы пользователь что-то напечатал с клавиатуры и чтобы
программа могла использовать эти данные, — input().

Переменные
Команду name = input() можно считать так: «Подожди, пока пользователь введет
какую-то строку и помести введенную строку в переменную name».
Попробуем разобраться, что это значит. Переменные имеют имя и значение.
Имя переменной
Имя переменной должно отражать ее назначение и может состоять из латинских букв,
цифр и символа подчеркивания.
Имя не может начинаться с цифры.
PEP 8
Для именования переменных принято использовать стиль
lower_case_with_underscores (слова из маленьких букв с подчеркиваниями).
Избегайте использовать такие символы, которые могут не однозначно трактоваться в
различных шрифтах: это буква О (большая и маленькая) и цифра 0, буква I (большая и
маленькая) и цифра 1. Нельзя использовать в качестве имени переменной и ключевые
слова, которые существуют в языке.
В вышеописанном примере переменная содержит в себе имя пользователя, поэтому
мы назвали ее name (имя). Обратите внимание: слово name не подсвечено никаким
цветом — в Python это слово ничего не обозначает. Оно что-то значит только в этой
программе и только потому, что мы употребили оператор присваивания. При этом
интерпретатору совершенно неважно, что значит слово name в английском языке, и
мы с тем же успехом могли использовать любое другое имя: например, user
(«пользователь») или просто n, или даже hello. За имена переменных отвечает
программист, то есть вы.
Соблюдайте правило: если в переменной хранится приветствие, пусть она так и
называется, если имя — пусть она и называется соответственно.
Значение переменной
Значение переменной — то, что сохраняет в себе переменная.
Знак «=» обозначает команду под названием «оператор присваивания». Оператор
присваивания присваивает значение, которое находится справа от знака равно,
переменной, которая находится слева от знака равно.
В нашем случае это то, что поместил в нее пользователь командой input(). Это
текстовое значение — строка. То есть переменная сохраняет в себе строковое
значение. Говорят, что переменная строкового типа.
PEP 8
Всегда окружайте оператор присваивания одним пробелом с каждой стороны:
Правильно:
bird = "Тук-тук"
Неправильно:
bird="Тук-тук"
Еще пример:
print('Какая твоя любимая еда?')meal = input()print('Да.', meal, '-
это вкусно.')
Обратите внимание: интерпретатор ждет, что пользователь что-то введет с клавиатуры
ровно столько раз, сколько команд input() встречается в программе. Каждый
input() завершается нажатием Enter на клавиатуре.
print('Как тебя зовут?')name = input()print('Привет,', name)print('А
какая твоя любимая еда?')meal = input()print('Да.', meal, '- это
вкусно.')
Мы задали значение переменной. И что же, оно никогда не меняется? Конечно, в двух
разных программах могут быть переменные с одинаковыми названиями, но разными
значениями. Но могут ли в пределах одной программы под одним именем быть
разные значения?
Да! Оператор присваивания сообщает переменной то или иное значение независимо
от того, была ли эта переменная введена раньше. Вы можете менять значение
переменной, записав еще один оператор присваивания. Если у нас имеется
переменная, мы можем делать с ее значением все что угодно — например, присвоить
другой переменной:
hello = 'Здравствуйте.'hello2 = helloprint(hello2)
Итак, если вы хотите, чтобы у вас была переменная с каким-то именем и каким-то
значением, нужно написать на отдельной строчке:
<имя переменной> = <значение переменной>
Как только эта команда выполнится, в программе появится указанная переменная с
таким значением.
Помните: команды выполняются последовательно, в том же порядке, в котором они
написаны.
А теперь смоделируем небольшой взлом программы.
Загрузите файл guessing_game.py. Это тоже программа на Python. Для начала просто
запустите ее (двойным кликом). Как видите, это игра-угадайка. Шанс угадать невелик,
у кого получится — тот везучий. Как бы облегчить выигрыш?
Теперь откройте эту программу в редакторе. Это делается не двойным кликом, а
кликом правой кнопкой и выбором пункта Edit with Wing IDE (или Редактировать с
помощью Wing IDE). Смысл некоторых строчек этой программы вы уже знаете. О
других скоро узнаете или сможете догадаться.
Сейчас мы научимся жульничать в игре путем изменения этой программы. Конечно,
можно было бы заменить всю программу единственной строчкой — поздравлением с
победой. Но мы будем считать, что менять можно только одну строчку — ту, которая
сейчас пуста. Мы можем вписать туда любую команду.
Мы знаем, что к тому моменту, когда выполнение программы доходит до пустой
строчки, в переменной под названием planet лежит название загаданной планеты.
Сделайте так, чтобы в этот момент оно выводилось прямо на экран, — тогда игроку
останется лишь повторить название для победы (это потребуется вам в задаче «Взлом
планетной угадайки»).

Трассировка
Задача (для разбора). Предположим, у нас есть программа, которая входит в
интерфейс сайта «Госуслуги» и служит для смены имени. Как будет работать эта
программа, что она выведет при каком-либо пользовательском вводе?
print('Введите фамилию:')surname = input()print('Введите имя:')name
= input()print(name, surname)print('Введите новое имя:')new_name =
input()print(name, surname)print(new_name, name)name =
new_nameprint(new_name, name)print(name, surname)
Давайте немного изменим программу и посмотрим, что теперь получится.
print('Введите фамилию:')surname = input()print('Введите имя:')name
= input()print(name, surname)print('Введите новое имя:')new_name =
input()old_name = namename = new_nameprint(new_name,
old_name)print(name, surname)
Если вы написали программу и не уверены в правильности ее написания, разберите,
что она делает. Если не уверены, что все сделали правильно, — запустите и проверьте
свои рассуждения.
Комментарии
Для удобства можно использовать комментарии, которые позволяют программисту
делать для себя пометки в коде или делать часть кода не выполнимой, не видимой
для интерпретатора.
Если вы начнете строчку со знака решетки #, интерпретатор Python будет игнорировать
всю эту строчку. Программа будет выполняться так, как будто строчки нет. Такая
строчка называется комментарием.
Комментарии нужны в двух случаях:

 Когда нужно добавить в программу какую-то пометку для человека, который


будет читать эту программу (например, см. третью строчку guessing_game).
 Когда нужно убрать какую-то строчку кода, но удалять ее не хочется (например,
потом ее, возможно, понадобится вернуть). Это называется
«закомментировать» строчку.
PEP 8
«Встрочные» комментарии находятся в той же строке, что и инструкция. Они должны
отделяться по крайней мере двумя пробелами от инструкции и начинаться с символа
# и одного пробела.
Комментарии в строке с кодом не нужны и только отвлекают от чтения, если они
объясняют очевидное.
Правильно:
x = x + 1 # компенсация границы
Неправильно:
x = x + 1 # увеличение на единицу
Если нужно закомментировать сразу несколько строчек подряд, не делайте это
вручную. Выделите эти строчки и выберите Source → Toggle block comment (там же
можно убрать комментирование).
Заметьте, что в конце guessing_game на отдельной строчке стоит знакомая команда
input(). Зачем она нужна?
Ответ: когда запускаешь программу двойным кликом, окно с программой закрывается
сразу, как только программа заканчивает работу. Если программа что-то выводит на
экран в конце работы, пользователь этого не увидит. А так программа ждет, пока
пользователь нажмет клавишу Enter. Конечно, он может что-то ввести, но это неважно
— мы все равно никак не используем этот ввод. Попробуйте закомментировать
последнюю строчку guessing_game и запустить программу из проводника двойным
кликом.
Заметьте: если запустить программу, у которой в конце input(), из редактора Wing
IDE, в конце ее работы придется лишний раз нажать Enter, хотя в этом и нет
необходимости.
Попробуйте запустить программу hello или любую другую из своих старых программ
двойным кликом — сначала в исходном виде, потом с input() в конце.
Условный оператор
Аннотация
Во втором уроке мы впервые познакомимся с одной из фундаментально важных
тем в программировании — условным оператором. Он позволяет организовать
ветвление в вашей программе (выполнение одной ветки кода в зависимости от
условия).

Повторение
На прошлом уроке мы познакомились с переменными. Переменная имеет имя и
значение. Имя переменной может начинаться только с буквы и включать в себя буквы,
цифры и символ подчеркивания. Имя переменной должно отражать ее назначение.
Чтобы задать переменной значение, необходимо после знака равно (оператора
присваивания) указать значение переменной.
Еще значение переменной можно получить из ввода. Для этого используем команду
input(). В этом случае значение переменной задает пользователь.

Условный оператор
Условный оператор используется, когда некая часть программы должна быть
выполнена, только если верно какое-либо условие. Для записи условного оператора
используются ключевые слова if и else («если», «иначе»), двоеточие и отступ в четыре
пробела.
if условие: Действия, если условие верноelse: Действия, если
условие неверно
PEP 8
Отступ в четыре пробела принят в сообществе Python (PEP 8). При этом программа
может работать и при других вариантах, но читать ее будет неудобно. Пробелы —
самый предпочтительный метод отступов.
Табуляция должна использоваться только для поддержки кода, написанного с
отступами с помощью табуляции.
Python 3 запрещает смешивание табуляции и пробелов в отступах.
Рассмотрим пример:
print('Введите пароль:')password = input()if password == 'qwerty':
print('Доступ открыт.')else: print('Ошибка, доступ закрыт!')
Обратите внимание: в начале условного оператора if выполняется сравнение, а не
присваивание. Разница вот в чем.
Сравнение
Сравнение — это проверка, которая не меняет значение переменной (в сравнении
может вообще не быть переменных), а присваивание — команда, которая меняет
значение переменной.
Для сравнения нужно использовать двойной знак равенства: ==.
Также заметьте, что после else никогда не пишется никакого условия.
Другой пример:
print('Представься, о незнакомец!')name = input()if name ==
'Цезарь': print('Аве, Цезарь!')else: print('Приветик.')
В качестве условия можно использовать и другие операции отношения:
< меньше> больше<= меньше или равно>= больше или равно== равно!= не
равно
PEP 8
Все операции отношения оформляются с помощью симметричных пробелов.
Правильно:
if bird == "Тук-тук":
Неправильно:
if bird=="Тук-тук":
Объекты любой однородной группы можно сравнивать между собой. Подумайте над
тем, как можно сравнивать, например, строки.

Сложное условие. Логические операции


Иногда в условном операторе нужно задать сложное условие. Для этого можно
использовать логические операции and («и»), or («или») и not («не»).
Чтобы задать одновременное выполнение двух условий, используем and («и»), если
достаточно выполнения одного из двух вариантов (или обоих сразу) — используем or
(«или»), а если нужно убрать какой-то вариант — not («не»).
Приоритет выполнения операций:
1. not2. and3. or
Если нужно изменить приоритет операций или вы забыли правила, используйте
скобки.
Например, вот так можно проверить, что оба условия выполнены:
print('Как называются первая и последняя буквы греческого
алфавита?')greek_letter_1 = input()greek_letter_2 = input()if
greek_letter_1 == 'альфа' and greek_letter_2 == 'омега':
print('Верно.')else: print('Неверно.')
Ниже еще несколько примеров.
print('Как греки или римляне называли главу своего пантеона - бога
грома?')ancient_god = input()if ancient_god == 'Зевс' or ancient_god
== 'Юпитер': print('Верно.')else:
print('Неверно.')print('Введите имена двух братьев из античных мифов
и легенд.')brother1 = input()brother2 = input()if brother1 ==
'Ромул' and brother2 == 'Рем' or brother1 == 'Кастор' and (brother2
== 'Поллукс' or brother2 == 'Полидевк'): print('Верно.')else:
print('Неверно.')
Обратите внимание: если программу из предыдущего примера вставить в IDE Wing,
часть кода условного оператора будет выходить за ограничительную красную черту
среды.

PEP 8
По стандарту PEP 8 длина строки должна быть ограничена максимум 79 символами.
Есть несколько способов переноса длинных строк.

 Использование подразумеваемых продолжений Python внутри круглых,


квадратных и фигурных скобок: длинные строки могут быть разбиты на
несколько строк, заключенных в скобки.
 Использование символа ’\’ (обратный слеш, или бэкслеш) для обозначения
места разрыва строки.
Мы будем использовать второй способ.
Если после перенесенной строки идет один или несколько вложенных операторов
(например, мы переносим строку с условием в операторе if), отступ у перенесенной
части должен быть на четыре пробела больше, чем у вложенного оператора.
Сделайте правильные отступы для перенесенной строки. Предпочтительнее вставить
перенос строки после логического оператора, но не перед ним.
Тогда представленный выше программный код может быть записан так:
print('Введите имена двух братьев из античных мифов и
легенд.')brother1 = input()brother2 = input()if brother1 == 'Ромул'
and brother2 == 'Рем' or brother1 == 'Кастор' and\ (brother2
== 'Поллукс' or brother2 == 'Полидевк'): print('Верно.')else:
print('Неверно.')
Рассмотрим еще несколько примеров.
print('Введите любые два слова, но это не должны быть "белый" и
"медведь" разом.')word1 = input()word2 = input()if not (word1 ==
'белый' and word2 == 'медведь'): print('Верно.')else:
print('Неверно.')
А теперь попробуйте решить задачи: «Елочка, гори», «Елочка-2», «Елочка-3».

Вложенные условия
Блок кода
В команде if при выполнении условия можно выполнять более одной команды. Для
этого все их необходимо выделить отступом. Такая запись называется блоком кода.
По отступам интерпретатор определяет, при выполнении каких условий какие
команды исполнять. Аналогично можно делать и для команды else.
print('Представься, о незнакомец!')name = input()if name == 'Цезарь'
or name == 'Caesar': print('Аве, Цезарь!') print('Слава
императору!')else: print('Приветик.') print('Погода сегодня
хорошая.')print('Засим - заканчиваем.')
Перед последней строчкой нет отступа, это означает, что она будет выполнена в конце
работы программы в любом случае. А вот две предыдущие строчки будут выполнены,
только если условие if окажется ложным.
Блоки кода в Python очень гибко устроены: внутри них можно писать любой другой
код, в том числе условные операторы. Среди команд, которые выполняются, если
условие if истинно («внутри if») или ложно («внутри else»), могут быть и другие
условные операторы. Тогда команды, которые выполняются внутри этого внутреннего
if или else, записываются с дополнительным отступом.
Изучите пример ниже. elif — это короткая запись для «else: if». Если не
пользоваться короткой записью, if пришлось бы писать на отдельной строчке и с
отступом (а все, что внутри этого if, — с дополнительным отступом). Это не очень
удобно, и elif избавляет от такой необходимости.
print('Представься, о незнакомец!')name = input()if name == 'Цезарь'
or name == 'Caesar': print('Аве, Цезарь!') print('В честь
какого бога устроим сегодня празднество?') god = input() if
god == 'Юпитер': print('Ура Громовержцу!') # если
оказалось, что имя бога не 'Юпитер', то проверяем, # не равно ли
оно строке 'Минерва' elif god == 'Минерва': print('Ура
мудрой воительнице!') # следующая строка будет выполнена, #
только если имя бога не 'Юпитер' и не 'Минерва' else:
print('Бога по имени', god, 'мы не знаем, но слово Цезаря - закон.')
# эта команда будет выполнена независимо от того, # какое имя
бога ввёл пользователь, если только изначально # он представился
Цезарем print('Слава императору!') else: print('Приветик.')
print('Погода сегодня хорошая.')print('Засим - заканчиваем.')
А более простой вариант этой программы теперь попробуйте написать
самостоятельно.

Операции над строками


Во всех примерах, которые мы рассматривали, переменные хранили строки. Мы
вводили, выводили и хранили строки. Кроме уже описанных действий, строки еще
можно складывать.
Давайте попробуем:
x = '10'y = '20'z = x + yprint(z)
PEP 8
И опять немного рекомендаций по оформлению (PEP 8): ставьте пробелы вокруг
знаков операций (*, +, - и т. д.)
Правильно:
z = x + y
Неправильно:
z = x+y
В данной программе мы задали переменным x и y значение, переменной z присвоили
значение результата сложения x и y.
Результатом выполнения программы будет строка 1020.
Конкатенация
Операция сложения для строк выполняет конкатенацию двух строк, то есть склеивает
их содержимое вместе.
Например: операция «При» + «вет» в результате даст строку «Привет».
Обратите внимание: запись: x + y = z недопустима. Оператор присваивания
ожидает слева переменную, которой надо присвоить значение, а в правой части
находится значение или выражение, которое надо сначала вычислить, а затем
присвоить.
Мы могли сократить нашу программу и написать в таком виде:
x = '10'y = '20'print(x + y)
Результат будет такой же, проверьте. Оператор print() сначала вычислил значение
выражения x + y, а потом вывел на экран полученное значение.
А еще такой результат можно получить вот таким образом:
print('10' + '20')
Дублирование
Для строк также можно выполнять умножение. Умножать можно строку на число или
число на строку. Операция называется дублирование. В результате нее начальная
строка будет повторена заданное количество раз.
Например: 3 * "20" то же, что и "20" * 3 и , результат будет 202020 и в том, и в
другом случае.
Примеры использования:
x = '10'y = '20'print(x * 2 + y * 3)
Что будет на экране после запуска такой программы?

Команда in
Теперь рассмотрим новую команду для работы со строками — команду in.
Команда in
Команда in позволяет проверить, что одна строка находится внутри другой.
Например: строка «на» находится внутри строки «сложная задача».
В таком случае обычно говорят, что одна строка является подстрокой для другой.
text = input()if 'хорош' in text and 'плох' not in text:
print('Текст имеет положительную эмоциональную окраску.')elif 'плох'
in text and 'хорош' not in text: print('Текст имеет отрицательную
эмоциональную окраску.')else: print('Текст имеет нейтральную или
смешанную эмоциональную окраску.')
Первое условие окажется истинным, например, для строк «все хорошо» и «какой
хороший день», но не для «ВсЕ ХоРоШо» и не для «что-то хорошо, а что-то и плохо».
Аналогично второе условие окажется истинным для строк «все плохо», «плохое
настроение» и т. д.
Простые встроенные функции
Аннотация
В этом уроке мы познакомимся с типами данных, научимся работать с числами и
узнаем о простейших функциях.

Повторение
На прошлом уроке мы рассмотрели условный оператор, который позволяет выполнять
различные ветки кода в зависимости от заданных условий. Научились составлять
сложные условия при помощи операций not, and и or.

Типы данных
Пока единственным типом данных, с которым мы работали, были строки. Теперь нам
предстоит рассмотреть целые и вещественные числа. У каждого элемента данных,
который встречается в программе, есть свой тип. (В случае с Python более правильный
термин — «класс объекта», но об этом мы будем говорить гораздо позже).
Например, «привет» — это строка, а вот 15.3 — это число (дробное). Даже если данные
не записаны прямо в программе, а получаются откуда-то еще, у них есть совершенно
определенный тип. Например, на место input() всегда подставляется строка, а 2 + 2
даст именно число 4, а не строку "4".
Пользователь может ввести с клавиатуры какие-то цифры, но в результате input()
вернет строку, состоящую из этих цифр. Если мы попытаемся, например, прибавить к
этой строке 1, получим ошибку.
Давайте попробуем это сделать:
a = input()print(a + 1)
Сохраните и запустите программу. Введите любое число и посмотрите, что получится.
Ошибка возникнет потому, что в переменную а у нас попадает строка, а в функции
print мы пытаемся сложить эту строку из переменной а и число 1. Исправьте
программу так, чтобы она работала.
А если нам надо работать с числами? Мы пока будем рассматривать целые и
вещественные числа.
Когда речь идет о числовых данных, они записываются без кавычек.
А для вещественных чисел, чтобы отделить дробную часть от целой, используют точку.
На прошлом занятии мы складывали две строки:
print('10' + '20')
И получали результат — строку "1020".
Давайте попробуем в этом примере убрать кавычки. В таком случае речь пойдет уже
не о строках, а о двух целых числах.
И результатом функции print(10 + 20) будет целое число 30.
А если мы попробуем сложить два вещественных числа print(10.0 + 20.0),
результатом будет вещественное число 30.0.
Попробуйте предположить, что будет, если сложить вещественное число и целое
число print(10.0 + 20). Почему?

Операции над числами


Мы выполняли сложение двух чисел внутри функции print, но мы можем переменным
давать нужные значения и выполнять действия над переменными.
Давайте напишем программу, которая задаст нужные значения двум переменным (10
и 20), потом вычислит их сумму, положит это значение в третью переменную и
выведет на экран полученный результат. Допишите начальные строки, чтобы
программа решала поставленную задачу:
...print(summ)
Обратите внимание: если в качестве имени переменной для суммы взять sum, оно
выделяется цветом. Это означает, что такое имя знакомо среде и принадлежит какой-
то функции, в качестве имени переменной его лучше не использовать.
Как складывать два числа, мы научились. Еще числа можно вычитать, умножать,
делить, возводить в степень, получать целую часть от деления и остаток от деления
нацело. Давайте разберем эти операции на примерах.
print(30 - 10)print(30.0 - 10)print(3 * 3)
С вычитанием и умножением все понятно, они аналогичны сложению.
Возведение в степень обозначается двумя звездочками **, которые должны
записываться без разделителей.
print(9 ** 2)
Обратите внимание: результат деления всегда вещественный, даже если мы делим
два целых числа, которые делятся нацело.
print(10 / 2)
Попробуйте поделить на 0. Посмотрите, как будет выглядеть ошибка деления на 0.

Целочисленное деление
Для реализации целочисленного деления существуют два действия: деление нацело и
остаток от деления нацело. Получение целой части от деления обозначается как
удвоенный знак деления, а остатка от деления нацело — %.
Давайте подробнее разберем эти операции. Что будет выведено в результате этих
действий?
print(10 // 3, 10 % 3)print(10 // 5, 10 % 5)print(10 // 11, 10 % 11)
Допустим, вам известны результаты a // b, a % b и число b, напишите формулу, как
найти число a?
Давайте проверим вашу формулу:
a = 10b = 3print(…А сюда напишем формулу…)
Обратите внимание на порядок выполнения действий в вашей формуле.
Целочисленное деление имеет тот же приоритет, что и обычное деление, значит,
будет выполнятся раньше, чем вычитание и сложение. Для изменения приоритета
выполнения операций используются скобки, все так же, как в математике.
А теперь, немного разобравшись с этими операциями, попробуйте предположить, что
выведется на экран после выполнения следующего куска кода:
print(10 // 3, 10 % 3)print(-10 // 3, -10 % 3)
Определите, что будет выведено на экран?
a = 4b = 15c = b / 5 * 3 - aprint(c)

Приоритет операций
Мы уже изучили несколько типов операций в языке Python:

 Операции присваивания (=, +=, -=, *= и т. д.)


 Операции сравнения (==, !=, >, <, >=, <=)
 Арифметические операции (+, -, *, /, %, //)
 Логические операции (and, or, not)
Есть и другие, с которыми познакомимся позднее. Все эти операции могут
использоваться совместно в довольно сложных конструкциях, поэтому нужно помнить
о приоритете операций и в случае необходимости менять его при помощи скобок.
Итак, приоритет выполнения операций в Python от высшего (выполняется первой) до
низшего:

 Возведение в степень (**).


 Унарный минус (-). Используется для получения, например, противоположного
числа.
 Умножение, деление (* / % //).
 Сложение и вычитание (+ -).
 Операции сравнения (<= < > >=).
 Операции равенства (== !=).
 Операции присваивания (=).
 Логические операции (not or and).
PEP 8
Если используются операции с разными приоритетами, попробуйте добавить пробелы
вокруг операций с самым низким приоритетом. Руководствуйтесь своими
собственными суждениями, но никогда не используйте более одного пробела и всегда
используйте одинаковое количество пробелов по обе стороны бинарной операции.

Простейшие функции
С действиями над числами определились, осталось разобраться, как получать числа из
ввода. Здесь нам поможет важное новое понятие — функция. В математике функция
из одного числа (или даже нескольких) делает другое.
Функция
В программировании (и в Python, в частности) функция — это сущность, которая из
одного (или даже нескольких) значений делает другое. При этом она может еще и
выполнять какие-то действия.
Например, есть функция модуля у = |x|, аналогично в Python есть функция y =
abs(x).
Но функции в Python необязательно принимают только числа.
Для того чтобы вводить числа с клавиатуры и потом работать с ними, необходимо
найти функцию, которая из строки делает число. И такие функции есть!
Тип данных целых чисел в Python называется int, дробных чисел — float.
Одноименные функции принимают в качестве аргумента строку и возвращают число,
если в этой строке было записано число (иначе выдают ошибку):
a = input()b = int(a)print(b + 1)
Или можно написать даже так:
a = int(input())
что будет означать — «получи строку из ввода, сделай из нее целое число и результат
помести в переменную а».
И тогда предыдущая программа может быть записана в виде:
a = int(input())print(a + 1)
Но можно сократить код еще, написав вот так:
print(int(input()) + 1)
Функция int может быть применена и для получения целого числа из вещественного, в
таком случае дробная часть будет отброшена (без округления).
Например, print(int(20.5 + 34.1)) выдаст на экран число 54, хотя, если сложить
эти числа и не отправлять их в фунцкию int, результат будет 54.6.
Попробуйте решить задачи: «Сложить два числа», «Сложить еще два числа», «Одно
число».
В Python cуществует огромное количество различных функций, мы будем знакомиться
с ними постепенно. Так, например, для строки можно определить еще и ее длину.
Длина строки
Длина строки — это количество символов в строке.
Для определения длины строки используется стандартная функция Python len().
На примере функции len разберемся с основными понятиями, связанными с
использованием функций. Изучите код:
word = input()length = len(word)print('Вы ввели слово длиной',
length, 'букв.')
Использование в программе функции называется «вызов функции». Он устроен так:
пишем имя функции — len, а затем в скобках те данные, которые мы передаем этой
функции, чтобы она что-то с ними сделала. Такие данные называются аргументами.
В нашем примере данные в скобках должны быть строкой. Мы выбрали в качестве
данных значение переменной word, которое пользователь до этого ввел с клавиатуры.
То есть значение переменной word выступает здесь в роли аргумента. А функция len
выдает длину этой строки. Если пользователь ввел, например, «привет», word
оказывается равно строке «привет», и на место len(word) подставляется длина
строки «привет», то есть 6.
Обратите внимание: каждый раз, когда мы пишем имя переменной (кроме самого
первого раза — в операции присваивания слева от знака равно), вместо этого имени
интерпретатор подставляет значение переменной.
Точно так же на место вызова функции (то есть имени функции и ее аргументов в
скобках) подставляется результат ее работы, это называется возвращаемое значение
функции.
Таким образом, функция len возвращает длину своего аргумента. input — тоже
функция (отсюда скобки), она может работать, не принимая никаких аргументов, а
может в качестве аргумента принимать сообщение, которое надо вывести перед
ожиданием пользовательского ввода. Но всегда считывает строку с клавиатуры и
возвращает ее.
print — тоже функция, она не возвращает никакого осмысленного значения, зато
выводит свои аргументы на экран. Эта функция может принимать не один аргумент, а
сколько угодно. Несколько аргументов одной функции следует разделять запятыми.
На самом деле функция сама по себе — это фактически небольшая программа, но об
этом позже.
Функции безразлично происхождение значений, которые ей передали в качестве
аргумента. Это может быть значение переменной, результат работы другой функции
или записанное прямо в коде значение:
print('Это слово длиной', len('абракадабра'), 'букв.')
Обратите внимание: в предыдущем примере значение переменной word вообще
никак не изменилось от вызова функции len. C другой стороны, вызов функции может
стоять где угодно, необязательно сразу класть возвращаемое значение в переменную.
Как существует функция int, которая пытается сделать из того, что ей передали, целое
число, так же существует и функция str, которая возвращает строку из тех данных, что в
нее передали.
print(str(10) + str(20)) # выведет '1020'print(int('10') +
int('20')) # выведет 30
Каждый раз, когда вы пишете программу, важно понимать, какой тип имеет каждое
значение и каждая переменная.

Обмен значениями переменных


Мы изучили операции с различными типами данных.
Давайте попробуем написать программу, которая поменяет местами содержимое
переменных а и b. Пусть есть такой код:
a = 3b = 5......print(a)print(b)
Что надо вписать в пропущенные места, чтобы в а лежало 5, а в b лежало 3? При этом
числами 3 и 5 пользоваться нельзя.
Как один из вариантов можно использовать дополнительную переменную:
a = 3b = 5с = aa = bb = cprint(a)print(b)
А теперь попробуйте написать вариант без дополнительной переменной, через сумму
двух чисел.
Но нам повезло, что мы изучаем язык Python, потому что он и поддерживает более
простой вариант записи:
a = 3b = 5a, b = b, aprint(a)print(b)
Значения переменных, которые расположены справа от знака «присвоить», в
указанном порядке помещаются в переменные слева, в порядке их указания.
Так, используя множественное присваивание, можно задавать нескольким
переменным одно значение:
a = b = c = 5
Знакомство с циклом while
Аннотация
В этом уроке мы познакомимся с оператором цикла while. Цикл
позволяет повторять организовать многократное повторение одних и тех
же действий. Кроме того, мы сделаем акцент вот на чем: в одной и
той же строчке программы на разных итерациях цикла переменные могут
иметь разное значение.

Цикл while
Сегодня мы научимся повторять заданные действия несколько раз. Для
этого существуют операторы циклов. Мы разберем оператор цикла while.
Он выполняет блок кода, пока истинно какое-то условие.
Напомним, условный оператор if проверяет условие и, в зависимости от
того, истинно оно или ложно, выполняет либо не выполняет следующий
записанный с отступом блок. После этого программа в любом случае
выполняется дальше (там еще может быть elif или else, но сути это не
меняет).
Цикл while
Оператор while («пока») тоже проверяет условие и тоже, в случае его
истинности, выполняет следующий блок кода (тело цикла). Однако после
выполнения этого блока кода выполняется не то, что идет после него,
а снова проверяется условие, записанное после while.
Ведь при выполнении тела цикла значения каких-то переменных могли
измениться — в результате условие цикла может уже не быть истинным.
Если условие все еще истинно, тело цикла выполняется снова. Как
только условие цикла перестало выполняться (в том числе если оно с
самого начала не было выполнено), программа идёт дальше —
выполняются команды, записанные после тела цикла.
Условие цикла записывается как и для if: с помощью операций
отношения (>, >=, <, <=, !=, ==). Cложные условия можно составлять с
помощью логических операций not, and, or.
Действия, расположенные в теле цикла (блок кода), записываются со
смещением вправо на четыре пробела относительно начала слова while.
Переменные, входящие в условие, должны на момент проверки условия
цикла иметь значения.
while условие: блок кода (тело цикла)
Важно!
Один шаг цикла (выполнение тела цикла) еще называют итерацией.
Используйте цикл while всегда, когда какая-то часть кода должна
выполниться несколько раз, причем невозможно заранее сказать,
сколько именно.
Давайте посмотрим программу, в которой цикл будет выполняться, пока
не введут число меньше 0:
number = int(input())while number > 0: print('Вы ввели
положительное число! Вводите дальше.') number = int(input())
print('Так-так, что тут у нас...')print('Вы ввели отрицательное
число или ноль. Всё.')
Разберемся, как будет работать эта программа.
Сначала выполняется первая строчка: number = int(input()) —
пользователь вводит целое число. (Мы предполагаем, что пользователь
действительно ввел число, и программа не вылетела с ошибкой.)
Предположим, он ввел число 10. Оно записано в переменной number.
Выполняется вторая строчка: while number > 0: — «пока number > 0» —
здесь проверяется, выполнено ли условие number > 0. Поскольку мы
предположили, что number в этот момент равно 10, тогда условие
выполнено, поэтому дальше выполняется блок, записанный с отступом, —
тело цикла.
Третья строчка программы выводит на экран строку, тут все понятно.
Четвертая строчка вновь считывает с клавиатуры число и сохраняет его
в переменную number. Пусть пользователь ввел 2.
Когда выполнение программы доходит до конца тела цикла, происходит
возврат к заголовку цикла (второй строчке программы) и повторная
проверка условия. Поскольку 2 > 0, снова выполняется тело цикла.
Третья строчка снова выводит на экран сообщение, четвертая строчка
снова считывает число (пусть это будет число 3), пятая строчка снова
выводит на экран сообщение...
Закончив тело цикла, опять проверяем условие в заголовке. number
равно 3, 3 > 0, поэтому продолжаем.
Третья строчка опять выводит на экран сообщение, четвертая строчка
опять считывает число. Пусть теперь это будет −1. Обратите внимание:
переменная number на каждой итерации цикла приобретает новое
значение! Пятая строчка опять выводит на экран сообщение...
Вновь вернувшись на вторую строчку, получаем, что −1 > 0 — ложно.
Поэтому цикл завершается, тело цикла больше не выполняется, прыгаем
сразу на следующую после цикла строчку программы — шестую. Она
выводит последнее сообщение.
Все.

Составной оператор присваивания


Напомним, что в операторе присваивания одно и то же имя переменной
может стоять и справа (в составе какого-то выражения), и слева. В
этом случае сначала вычисляется правая часть со старым значением
переменной, после чего результат становится новым значением этой
переменной. Ни в коем случае не воспринимайте такой оператор
присваивания как уравнение!
number = int(input()) # например, 5number = number + 1 # тогда
здесь number становится равным 6print(number)
Важно!
Для конструкций вида number = number + 1 существует и сокращенная
форма записи оператора присваивания: number += 1. Аналогично
оператор x = x + y можно записать как x += y, оператор x = x * y —
как x *= y, и так для любого из семи арифметических действий.

Сигнал остановки
Рассмотрим такую задачу: пользователь вводит числа. Пусть это будут
цены на купленные в магазине товары, а наша программа — часть
программного обеспечения кассового аппарата. Ввод −1 — сигнал
остановки. Нужно сосчитать сумму всех введенных чисел (сумму чека).
Поскольку требуется повторить нечто (ввод очередной цены)
неизвестное количество раз, потребуется цикл while. Нам понадобится
как минимум две переменные: price для цены очередного товара и total
— для общей суммы.
Если бы мы знали точно, что пользователю надо купить ровно три
товара, цикл (и ввод −1 как условие его прерывания) был бы не нужен.
Тогда программа могла бы выглядеть так:
total = 0price = float(input())total = total + price price =
float(input())total = total + price price = float(input())total =
total + priceprint('Сумма введённых чисел равна', total)
Обратите внимание: мы назвали переменные осмысленно. Это очень
облегчит жизнь программисту, который будет читать наш код позже,
даже если это будете вы сами неделю спустя. Однако интерпретатор
Python к этому факту совершенно равнодушен. Чтобы значения
переменных соответствовали названиям и тому смыслу, который мы в них
закладываем, нужно поддерживать переменные в актуальном состоянии. И
только вы, программист, можете это сделать.
С переменной price все относительно понятно: ее значение обновляется
при считывании с клавиатуры на каждой итерации цикла, как это
делалось во многих других задачах. total сначала равно нулю: до
начала ввода цен их сумма, конечно, ноль. Однако значение переменной
total устаревает каждый раз, когда пользователь вводит цену
очередного товара. Поэтому нам нужно прибавить к значению total
только что введенную цену, чтобы эта переменная по-прежнему
обозначала сумму цен всех купленных товаров.
Если бы мы хотели сократить запись, можно было бы организовать цикл,
который выполнился бы ровно три раза. Для этого нам потребуется
переменная-счетчик, которая внутри цикла будет считать каждую
итерацию цикла. А условием выхода обозначим выполнение нужного
количества итераций:
count = 0total = 0while count < 3: price = float(input())
total = total + price count = count + 1print('Сумма введённых
чисел равна', total)
Обратите внимание: total и count должны обнуляться до цикла.
Однако у нас в задаче количество товаров неизвестно, поэтому
понадобится цикл до ввода сигнала остановки (−1). С учетом
сказанного выше программа будет выглядеть так:
total = 0print('Вводите цены; для остановки введите -1.')price =
float(input())while price > 0: total = total + price # можно
заменить на аналогичную запись # total += price price =
float(input())print('Общая стоимость равна', total)

Подсчет количества элементов, удовлетворяющих условию


А теперь рассмотрим еще одну задачу.
Пользователь вводит целые числа. Ввод чисел прекращается, если
введено число 0. Необходимо определить, сколько чисел среди
введенных оканчивались на 2 и были кратны числу 4. Теперь нам надо
проверять последовательность чисел.
Для каждого введенного числа надо делать проверку, соответствует ли
оно условию. Если оно подходит под условие, увеличиваем счетчик
таких чисел.
И уже после цикла, когда остановился ввод чисел, выводим результат —
посчитанное количество нужных чисел.
count = 0number = int(input())while number != 0: if number % 10
== 2 and number % 4 == 0: count += 1 number =
int(input())print('Количество искомых чисел:', count)
Обратите внимание: до цикла необходимо задать начальное значение для
переменной count. Ведь когда придет первое подходящее под условие
число, у нас count будет увеличиваться на 1 относительно предыдущего
значения. А значит, это значение должно быть задано.
Давайте посмотрим, как будет работать эта программа для
последовательности чисел: 12, 3, 32, 14, 0.
Шаг Действие Пояснение Цикл
1 count = 0 count = 0
2 number = number = 12
int(input())
3 while number != 12 != 0 (Истина) Вход в цикл, 1-я
0: итерация
4 if number % 10 12 % 10 == 2 and Заходим в if
== 2 and number 12 % 4 == 0
% 4 == 0: (Истина)
5 count += 1 count = 1
6 number = number = 3
int(input())
7 while number != 3 != 0 (Истина) 2-я итерация
0:
8 if number % 10 3 % 10 == 2 and Пропускаем if
== 2 and number 3 % 4 == 0 (Ложь)
% 4 == 0:
9 number = number = 32
int(input())
10 while number != 32 != 0 (Истина) 3-я итерация
0:
11 if number % 10 32 % 10 == 2 and Заходим в if
== 2 and number 32 % 4 == 0
% 4 == 0: (Истина)
12 count += 1 count = 2
13 number = number = 14
int(input())
14 while number != 14 != 0 (Истина) 4-я итерация
0:
15 if number % 10 14 % 10 == 2 and Пропускаем if
== 2 and number 14 % 4 == 0 (Ложь)
% 4 == 0:
16 number = number = 0
int(input())
17 while number != 0 != 0 (Ложь) Выход из цикла
0:
18 print('Количеств Вывод вычисленного
о искомых count
чисел:', count)
Поиск максимума и минимума
Очень часто в задачах приходится использовать различные
статистические алгоритмы: поиск максимума, минимума, среднего
значения, медианы и моды чисел, главный из которых — определение
максимального и минимального значений на множестве данных.
Рассмотрим алгоритм в общем виде.

 Заведем отдельную переменную для хранения максимума и


минимума. В качестве начального значения можно задать:
o Заведомо малое для анализируемых данных значения, для
максимума это будет совсем маленькое число: например,
если мы вычисляем максимальный балл за экзамен, можно
взять maximum = 0, тогда гарантированно произойдет замена
максимума. Минимуму же, наоборот, присваивается заведомо
большое значение
o Первый элемент данных
 В теле цикла каждый подходящий элемент данных обрабатывается
операторами по принципу:
o Если текущий элемент больше максимума, меняем максимум
o Если текущий элемент меньше минимума, заменяем минимум
Рассмотрим пример. Витя анализировал список литературы и решил, что
хочет начать с самой большой по объему книги. Напишем программу,
которая поможет мальчику определить, сколько страниц ему предстоит
прочитать. Витя последовательно вводит количество страниц каждой
книги из списка, а окончанием ввода служит ввод любого
отрицательного числа.
biggest_book = 0n = int(input())while n > 0: if n > biggest_book:
biggest_book = n n = int(input())print(biggest_book)
Так как книга не может содержать в себе 0 страниц, для значения
максимума мы можем взять 0.
После этого Витя начинает вводить количество страниц: например, он
вводит 148. 148 > 0 — условие цикла выполняется, и мы переходим к
операции сравнения. На данном шаге 148 > 0, значит, biggest_book =
148. Снова считываем число.
Предположим теперь введено 120. 120 > 0 — продолжаем работать в
цикле. 120 > 148 — условие не выполняется, переходим к вводу новых
данных, biggest_book все еще равен 148.
В этот раз мальчик ввел 486, мы заходим в цикл 486 > 148, производим
замену biggest_book = 486. Продолжаем ввод. И так далее до тех пор
пока не будет введено отрицательное число.
Отладчик
Аннотация
В уроке рассматривается работа с отладчиком на примере программы,
которую нужно исправить. Затем даются группы задач, алгоритмы
решения которых требуют рассмотрения многих случаев. В этом уроке
нет тестов к задачам, точно так же, как на контрольных и
самостоятельных работах. Вам придется самим выяснять, на каких
входных данных не работает ваша программа. Внимательно читайте
условие.

Типы ошибок
Вероятно, вы уже обратили внимание, что при написании программ у вас
возникали хоть и разные ошибки, но у многих из них было что-то
общее. На самом деле существуют три основных типа ошибок, которые
нужно научиться различать, так вы сможете без труда их исправить.
Синтаксическая ошибка: происходит, когда встречается код, который не
соответствует правилам языка Python. Например: отсутствие кавычек
вокруг строковой переменной, невыставленное двоеточие или отсутствие
отступов после оператора if. Интерпретатор останавливается и
сообщает об ошибке без дальнейшего выполнения программы.
Ошибка исполнения: как следует из названия, случается во время
исполнения программы. Например, когда переменная ожидает работу с
целыми числами, а оказывается строкой. Из-за несоответствия типов
интерпретатор останавливается на ошибке.
Логическая ошибка (смысловая): происходит, когда программа ведет
себя не так, как было задумано. Например, порядок действий в
вычисляемом выражении задан неправильно или неверно были расставлены
отступы во вложенных операторах условия и т. д. Интерпретатор
запускает программу и не сообщает об ошибке. Но все работает не так,
как хотелось бы.
С исправлением первых двух типов ошибок справиться достаточно
просто, поскольку интерпретатор сообщает, где ошибка произошла, а в
среде разработки чаще всего указывается строка, на которой эта
ошибка возникла. А для логических ошибок требуется детальное
изучение кода, чтобы найти такие ошибки, разработан специальный
механизм отладки.

Отладка
Отладка
Процесс изучения и исправления ошибок в работе программы (их часто
называют багами, от англ. bug — жук), называется отладкой, по-
английски — debugging, одно из значений — «удаление насекомых с
растений». По одной из версий, именно так приходилось чинить
компьютеры на заре компьютерной эпохи.
Программист всегда тестирует программу, занимается трассировкой и,
конечно, размышляет над кодом, но иногда этого недостаточно. Часто
(особенно когда программа длинная и сложная) невозможно обойтись без
дополнительной информации. Какое значение имеет такая-то переменная
в такой-то момент работы программы? В таком-то месте выполняется if
или else? Выполняется ли тело такого-то цикла и, если да, сколько
раз?
Для ответа на такие вопросы существуют специальные инструменты
отладки (отладчики). Они позволяют проходить программу пошагово и
следить при этом за значениями переменных.
Средства отладки есть в стандартной библиотеке функций Python, но
обычно удобнее пользоваться возможностями среды программирования.
Рассмотрим возможности отладчика Wing IDE на примере программы из
прошлого урока.
total = 0print('Вводите цены; для остановки введите -1.')price =
float(input())while price > 0: total = total + price # можно
заменить на аналогичную запись # total += price price =
float(input())print('Общая стоимость равна', total)
Возьмем вот эту программу. Запустим ее, убедимся, что она работает.
Попробуем пройти по ней в режиме отладки.
Средства отладки расположены в меню Debug и выведены иконками (после
кнопки запуска) в панели меню. Еще их можно запускать горячими
клавишами.

В меню Debug есть такие команды (обратите внимание и на горячие


клавиши, указанные справа):

 Start / Continue и Stop Debugging. Кнопки Debug и Stop


выполняют те же функции. Первая команда запускает выполнение
программы до ближайшего breakpoint’а, вторая полностью
прерывает процесс отладки.
 Step Into, Step Over, Step Out, Step Out to Here. Управление
пошаговым прохождением программы. Мы пока будем использовать
только Step Over. Остальные пункты связаны с заходом внутрь
функций и выходом из них, но мы свои функции пока не пишем, а
заходить внутрь стандартных нам не нужно. Пункт Step Over (как
и одноименная кнопка) доступен, когда программа запущена, но
остановлена по breakpoint’у. Нажатие этой кнопки выполняет
команду, записанную на текущей строчке, переходит на следующую
и останавливается, ожидая еще одного Step Over либо Continue.
 Из следующих пунктов нам пока понадобятся только Add
Breakpoint и Remove All Breakpoints. Add Breakpoint, как и
кнопка Break, добавляет точку остановки на ту строчку
программы, где находится курсор.
Важно!
Если вы не видите подписей под кнопками, их можно включить: Edit →
Preferences... → User Interface → Toolbar → Toolbar Style → Icon and
Text Below.

 Запустим отладку, выбрав из меню команду Step Into (или


одноименную кнопку или воспользуемся горячей клавишей F7).
После запуска этой команды вместо окна Python Shell стало
активно окно Debug I/O. В этом окне будет происходить
ввод/вывод данных при отладке. Первая строка программы
выделилась розовым цветом, и у номера строки появилась розовая
стрелка. Таким образом будет выделяться строка, которая будет
выполнена при следующем шаге отладки. На текущий момент мы
только запустили отладчик, первую строку программы он еще не
выполнил, а только собирается выполнить. В левом нижнем окне
переключитесь с активного окна Search на окно Stack Data. В
этом окне мы сможем просматривать значения переменных
 Теперь выполним первую команду программы (total = 0). Для
этого выберите команду Step Over. После выполнения этой
команды первая строка программы выполнилась. Посмотрите в окно
Stack Data. Там в разделе Local появилась переменная total,
которой присвоено значение 0
 Теперь будем выполнять строчку price = float(input()), в
которой требуется вводить данные. Выполните команду Step Over.
Перейдите в окно Debug I/O и введите любое число, например,
45. Ввод завершите клавишей Enter. Пока программа ждала от нас
ввода данных, окно Stack Data было неактивно и в окне
редактора не было розовой подсветки исполняемой строки. После
ввода данных и нажатия Enter окно Stack Data стало снова
активным, в нем появилась переменная price с заданным нами
значением. Значение переменной total пока не изменилось
 Выполним очередной шаг отладки (Step Over) и увидим, что
значение переменной total изменилось и стало равно значению
переменной price
Теперь самостоятельно продолжите отладку программы, выполняя команду
Step Over, когда необходимо вводя значения и наблюдая, как меняются
значения переменных в окне Stack Data.
Вы только что выполнили свою первую отладку программы!

Точка остановки
А теперь при помощи отладчика поищем ошибки в другой программе.
Рассмотрим вот такую программу под названием bank:
print('Добро пожаловать в интернет-банк!')print('У нас
фантастические процентные ставки!')print('Для вкладов до 10 тысяч ₽
включительно прибыль составит 10%,')print('для вкладов на сумму до
100 тысяч включительно - 20%,')print('для более 100 тысяч -
30%!')print('На какую сумму желаете сделать вклад?')money =
float(input())if money <= 10000: money *= 1.1if money <= 100000:
money *= 1.2if money > 100000: money *= 1.3print('Вы получаете',
money, '₽, поздравляем!')
Эта программа верно выводит 1 300 000, если ввести 1 000 000, и
верно выводит 24 000, если ввести 20 000. Но, если ввести 1000,
программа выведет 1320 вместо 1100, а если ввести 100 000 — выведет
156 000 вместо 120 000!
Выясним причины такого поведения при помощи инструментов отладки из
меню Debug. Посмотрим, какие команды выполняются и как меняется
значение переменной money.
Но если мы посмотрим на программу — начальные строчки нет смысла
отлаживать пошагово — в них выполняется вывод на экран. Есть смысл
делать отладку только с момента получения значения money.
Точка остановки
Если в строку, с которой начинается пошаговая отладка, поставить
специальную метку — точку остановки (breakpoint), тогда при
пошаговом выполнении можно выполнить все команды до breakpoint’а в
обычном режиме, а не пошагово.
Итак, отлаживаем программу bank.

 С помощью команды Add Breakpoint добавим точку остановки


(breakpoint) на строчке 8, поместив туда курсор. Обратите
внимание: тот же пункт меню теперь называется Remove
Breakpoint (но только пока курсор на этой строчке кода), а
перед строчкой появилась красная точка. Это индикатор
breakpoint’а. Можно убрать breakpoint, щелкнув мышкой по
красной точке, или установить его, щелкнув по этому месту на
этой или на другой строчке.
 Запустим программу, но не кнопкой Run, а кнопкой Debug. В окне
Debug I/O выведется текст из всех функций print и будет мигать
курсор, ожидая ввода данных. Введем сумму — например, 1000. В
этот момент программа доходит до строчки, на которой
установлен breakpoint, и временно прерывает работу, отметив
красным строку, на которой остановилась. В нижнем левом углу
во вкладке Stack Data можно увидеть список переменных и их
значения. Большинство — специальные системные, но в конце
списка есть и переменная money.
 Если теперь выбрать в меню Start / Continue, программа
продолжит работу до следующего breakpoint’а (которые можно
ставить и снимать прямо во время отладки) или до конца. Но нам
нужно пройти по программе построчно, чтобы понять, какие
команды выполняются и чему при этом равно значение money.
Чтобы продолжить выполнение программы, выберем команду Step
Over.
 Продолжаем нажимать Step Over. Обратите внимание: когда
программа выполнила строчку 9, значение money изменилось на
1100 — это верный итоговый ответ.
 Но что же дальше? После строчки 10, на которой программа
проверяет условие if, выполняется строчка 11, после которой
значение money увеличивается до неправильного! Неудивительно:
ведь условие и правда истинно. Но программа явно должна
работать по-другому
Исправьте программу так, чтобы она работала правильно.
На прошлом уроке мы смотрели, как работает цикл на примере
трассировочных таблиц. А теперь давайте посмотрим в режиме отладки,
как будет работать программа при вводе последовательности 12, 3, 32,
14, 0.
count = 0number = int(input())while number != 0: if number % 10
== 2 and number % 4 == 0: count += 1 number =
int(input())print('Количество искомых чисел:', count)
Пройдитесь по программе отладчиком, вводя указанные значения.
Согласитесь, что так отлаживать программы проще, чем делать это
вручную на бумаге.
А теперь выберите разные значения для переменных a и b и пройдитесь
отладчиком по данному коду:
a = int(input())b = int(input()) while a != b: if a > b: a
-= b else: b -= aprint(a)
Посмотрите, как будут меняться переменные. Определите, что будет
выводиться на экран при выбранных вами значениях. Что находит данная
программа для двух чисел?
Рассмотрим очередную задачу.
В программу поступают значения с температурного датчика. Ввод
значений прекращается сигналом остановки (число 0).
Вот код этой программы:
a = int(input())k = 0t = awhile a != 0: if a > t: t = a
k = 0 if a == t: k += 1 a = int(input())print(k)
Ваша задача — определить, что находит и выводит данная программа
относительно вводимых значений температуры?
При решении задач («Псевдонимы», «Лабиринт», «Бот-говорилка»)
помните, что они рассчитаны на людей. Пользователь должен понимать,
что и когда нужно вводить.
Знакомство с циклом for
Аннотация
В уроке рассматриваются именованные аргументы функции print,
специальные символы в строке и конструкция for ... in range(...):.

Именованные аргументы функции print


Мы уже пользовались тем, что функция print при выводе разделяет
аргументы пробелами, а в конце переходит на новую строчку.
Часто это удобно. Но что если от этого нужно избавиться? В примере
ниже пробелы появляются не только после двоеточий (что хорошо), но и
перед запятой (что плохо).
measures = 7cuts = 1print('Количество отмеров:', measures, ',
количество отрезов:', cuts)# выведет: "Количество отмеров: 7 ,
количество отрезов: 1"
Необязательные именованные аргументы
Для такой тонкой настройки вывода у функции print существуют
необязательные именованные аргументы — такие удобные инструменты
бывают и у других функций, мы познакомимся с ними позже.
Обычно при вызове функции мы пишем имя функции, а затем в скобках ее
аргументы через запятую. Стандартный способ сообщить функции, что и
с какими аргументами делать (например, какой из аргументов функции
print вывести первым, какой вторым и т. д.), — это передать
аргументы в нужном порядке. Например, функция print выводит
аргументы именно в том порядке, в котором их ей передали. Однако
есть и другой способ — именованные аргументы. Чтобы при вызове
функции передать ей именованный аргумент, нужно после обычных
аргументов написать через запятую имя аргумента, знак = и значение
аргумента.
sep и end
Функция print, наряду с другими аргументами, может (вместе или по
отдельности) принимать два следующих аргумента: sep — разделитель
аргументов (по умолчанию пробел) и end — то, что выводится после
вывода всех аргументов (по умолчанию символ начала новой строки).
В частности, если end сделать пустой строкой, то print не перейдет
на новую строчку, и следующий print продолжит вывод прямо на этой же
строке.
print('При')print('вет!') # эти две строки кода выведут "При" и
"вет!" на отдельных строкахprint('При', end='')print('вет!') # эти
две строки кода выведут "Привет!"print('Раз', 'два', 'три') #
выведет "Раз два три"print('Раз', 'два', 'три', sep='--') # выведет
"Раз--два--три"
Обратите внимание: знак = здесь не выполняет никакого присваивания,
переменных end и sep не появляется.
PEP 8
Не используйте пробелы вокруг знака =, если он используется для
обозначения именованного аргумента.
Правильно:
print('При', end='')
Неправильно:
print('При', end = '')

Специальные символы в строках


Можно задаться вопросом: как указать значение end по умолчанию —
символ начала новой строчки? Ведь это специальный символ, который
нельзя сделать частью строки, просто поместив его между кавычек, это
вызовет ошибку.
Экранирующая последовательность
Если внутри кавычек встречается символ \ — обратная косая черта,
обратный слеш, бэкслеш, он вместе с идущим после него символом
образует экранирующую последовательность (escape sequence) и
воспринимается интерпретатором как единый специальный символ.
В частности, \n — символ начала новой строки. Кроме того, \t —
табуляция, \' — кавычка, \\ — просто бэкслеш. Использование
экранирующих последовательностей вместо специальных символов
называется их экранированием.
print('восход\t07:15\nзакат\t22:03')print('Предыдущая строка этой
программы выглядит
так:')print('print(\'восход\\t07:15\\nзакат\\t22:03\')')
Таким образом, значения именованных аргументов функции print по
умолчанию такие: print(..., sep=' ', end='\n').
Важно!
При этом если приписать букву r перед открывающей строку кавычкой,
бэкслеши будут считаться обычными символами.
А если открывать и закрывать строку не одной, а тремя кавычками
подряд, внутри можно делать обычные переводы строки (внутри
одинарных кавычек так делать нельзя).
print(r'\\\\\\\nnnnn <- забор, переходящий в низкую
изгородь')print('''Нужно сказать много важного.Одной строки для
этого мало.Зато три - в самый раз.''')

Цикл for
Сегодня мы изучим еще один оператор цикла. Цикл for выполняет блок
кода заданное количество раз.
Синтаксис
for ... in range(...): блок кода (тело цикла)
Как и у while, у цикла for есть заголовок, заканчивающийся
двоеточием, и тело цикла, которое записывается с отступом в четыре
пробела. В цикле вида for ... in range(...): вместо первого
многоточия указывается какая-то переменная, которая на начальной
итерации принимает значение 0, на следующей — 1, и так далее, до
значения указанного в range(...), само это значение переменная не
принимает. Диапазон значений переменной-итератора от 0 включая и до
значения, указанного в range(...), не включая его.
Вот программа, которая выводит на экран подряд (на отдельных
строчках) целые числа от 0 (включительно) до n (не включительно).
n = int(input())for i in range(n): print(i)
Range
Range означает «диапазон», то есть for i in range(n) читается как
«для (всех) i в диапазоне от 0 (включительно) до n (не
включительно)...». Цикл выполняется n раз.
Давайте вспомним задачу, где мы три раза получали цены на товар и
вычисляли общую цену товара.
Вот так мы ее записали через цикл while:
count = 0total = 0while count < 3: price = float(input())
total = total + price count = count + 1print('Сумма введённых
чисел равна', total)
Теперь мы ее можем записать через цикл for, который будет
выполняться три раза:
total = 0for i in range(3): price = float(input()) total =
total + priceprint('Сумма введённых чисел равна', total)
В данном случае переменная-счетчик изменяется сама в рамках заданных
значений.
Запустите эту программу с отладчиком и пройдите ее пошагово. Можно
поставить breakpoint на первую же строчку или начать выполнение
программы кнопкой F7. Следите за тем, как меняется значение
переменной i. Обратите внимание, что цикл for присваивает переменной
i (она называется итератором цикла) значения (0, потом 1...), хотя
нигде нет оператора присваивания = или его родственников типа +=.

Соглашения об именовании переменных


В программах, решающих абстрактные, математические задачи, допустимо
называть переменные короткими и непонятными именами типа n или i.
Однако этого лучше избегать. Кроме того, стоит соблюдать
общепринятые договоренности: буквой n обычно обозначают количество
чего-либо (например, итераций цикла). При этом если есть хоть какая-
то определенность (например, речь идет о количестве автомобилей), то
стоит и переменную назвать более понятно (например, cars). Буквами i
и ;j (по-русски они традиционно читаются как «и» и «жи») обычно
обозначают итераторы цикла for.
Еще один пример: программа, подсчитывающая сумму всех целых чисел,
которые меньше данного.
n = int(input())total = 0for i in range(n): print('Рассматриваем
число', i) total += i print('Промежуточная сумма равна',
total)print('Итоговая сумма всех этих чисел равна', total)

Начальное значение и шаг итератора в range


Однако это не все возможности цикла for.
Предположим, вам нужен цикл, выполняющийся 10 итераций. При этом
нужно, чтобы итератор пробегал значения не подряд (0, 1, ..., 9), а,
скажем, 10, 20, ..., 100. Конечно, с помощью уже известной нам
конструкции for можно организовать цикл, в котором некая
дополнительная переменная будет последовательно принимать именно
такие значения (проверьте себя: как?).
Однако для этого есть и специальная встроенная в язык конструкция. В
скобках после слова range можно записать не одно, а два или три
числа. (Правда, очень похоже на функцию? Это не случайность, range —
тоже функция, но об этом позже). Эти числа будут интерпретироваться
как начальное значение итератора, конечное и его шаг (может быть
отрицательным).
Если для range задано одно число, то итератор идет от 0 до заданного
значения (не включая его).
Если задано два числа, то это начальное значение итератора и
конечное.
Если задано три числа, то это не только начальное и конечное
значение итератора, но и шаг итератора.
for i in range(1, 11): print(i) # выведет на отдельных строчках
числа # от 1 (включительно) до 11 (не включительно)for
i in range(1, 11, 2): print(i) # выведет (на отдельных строчках)
1, 3, 5, 7, 9for i in range(10, 0, -1): print(i) # выведет 10,
9, ..., 1

Когда какой цикл использовать


 Цикл while нужен, когда какой-то кусок кода должен выполниться
несколько раз, причем заранее неизвестно, сколько именно
 Цикл for нужен, когда какой-то кусок кода должен выполниться
несколько раз, при этом известно сколько раз еще до начала
цикла
True и false, break и continue
Аннотация
Этот урок посвящен условиям выхода из циклов. Рассматривается булев
тип, даются задачи на использование флагов. Затем рассматриваются
операторы break и continue, позволяющие в некоторых случаях
избавиться от флагов.

Логический тип данных


Если a и b — числа (допустим, действительные), то у выражения a + b
есть какое-то значение (зависящее от значений a и b) и тип — тоже
действительное число. Как вы думаете, можно ли сказать, что у
выражения a == b есть значение и тип? Или это просто конструкция,
которая всегда должна стоять в условии if или while?
Логический тип
На самом деле такое выражение имеет и тип под названием bool, и
значение: True (истина) или False (ложь). По-русски bool — это булев
тип, или булево значение (в честь математика Джорджа Буля), иногда
его еще называют логический тип.
Логический тип может иметь только два значения, а над переменными
логического типа можно выполнять логические операции not, and, or.
Также для приведения к логическому типу можно использовать функцию
bool, которая для ненулевого значения вернет истину.
k = Trueprint(k) # выведет Trueprint(not k) # выведет Falsek = 5 >
2print(k) # выведет Truek = bool(0)print(k) # выведет Falsek =
bool("")print(k) # выведет Falsek = bool(13)print(k) # выведет True,
т.к. число не 0k = bool("q")print(k) # выведет True, т.к. строка не
пустаяk = bool("False")print(k) # выведет True, т.к. строка не
пустая
Или вот еще пример:
if True: print('Эта строка будет выведена на экран.')else:
print('Эта строка никогда не будет выведена на экран.')print(2 * 2
== 4) # выведет Truea = input()b = input()# Теперь переменная equal
равна True, если строки a и b равны, # и False в противном
случаеequal = (a == b)if equal and len(a) < 6: print('Вы ввели
два коротких одинаковых слова.')
Использование флагов
Обычно переменные с булевым значением используются в качестве
флагов.
Флаг
Изначально флаг устанавливается в False, потом программа как-то
работает, а при наступлении определенного события флаг
устанавливается в True. После идет проверка, поднят ли флаг. В
зависимости от ее результата выполняется то или иное действие. Иными
словами, флаг — это переменная с булевым значением, которая
показывает, наступило ли некое событие.
В примере ниже (эта программа — терапевтический тренажер для
избавления физиков-экспериментаторов от синхрофазотронозависимости)
имеется флаг said_forbidden_word, который означает «сказал ли
пользователь запретное слово „синхрофазотрон“». Флаг равен True,
если сказал, и False, если нет.
В самом начале пользователь еще ничего не успел сказать, поэтому
флаг установлен в False. Далее на каждой итерации цикла, если
пользователь сказал запретное слово, флаг устанавливается в True и
остается в таком состоянии (при необходимости флаг можно и
«опустить»). Как только флаг оказывается равен True, поведение
программы меняется: перед каждым вводом выдается предупреждение, а в
конце выдается другое сообщение.
Важно!
Переменным-флагам особенно важно давать осмысленные имена (обычно —
утверждения вроде said_forbidden_word, found_value,
mission_accomplished, mission_failed), ведь флагов в программе
бывает много.
forbidden_word = 'синхрофазотрон'# можно было использовать и sep='',
чтобы кавычки не отклеились от словаprint('Введите десять слов, но
постарайтесь случайно не ввести слово "' + forbidden_word +
'"!')said_forbidden_word = Falsefor i in range(10): if
said_forbidden_word: print('Напоминаем, будьте осторожнее, не
введите снова слово "' + forbidden_word + '"!')
word = input() if word == forbidden_word:
said_forbidden_word = True # вместо предыдущих двух строк также
можно написать: # said_forbidden_word = (said_forbidden_word or
word == forbidden_word)if said_forbidden_word: print('Вы нарушили
инструкции.')else: print('Спасибо, что ни разу не упомянули',
forbidden_word)
Операторы break и continue. Бесконечные циклы
Если нужно прекратить работу цикла, как только случится некое
событие, то, кроме флага, есть и другой способ — оператор разрыва
цикла break (он работает и для цикла for). Это не функция и не
заголовок блока, а оператор, который состоит из одного слова. Он
немедленно прерывает выполнение цикла for или while.
for i in range(10): print('Итерация номер', i, 'начинается...')
if i == 3: print('Ха! Внезапный выход из цикла!')
break print('Итерация номер', i, 'успешно завершена.')print('Цикл
завершён.')
В частности, нередко встречается такая конструкция: цикл, выход из
которого происходит не по записанному в заголовке цикла условию (это
условие делается всегда истинным — как правило, просто True), а по
оператору break, который уже заключен в какой-то условный оператор:
while True: word = input() if word == 'стоп': break
print('Вы ввели:', word)print('Конец.')
Важно!
Впрочем злоупотреблять этой конструкцией и вообще оператором break
не стоит. Когда программист читает ваш код, он обычно предполагает,
что после окончания цикла while условие в заголовке этого цикла
ложно. Если же из цикла можно выйти по команде break, то это уже не
так. Логика кода становится менее ясной.
Оператор continue немедленно завершает текущую итерацию цикла и
переходит к следующей.
for i in range(10): print('Итерация номер', i, 'начинается...')
if i == 3: print('...но её окончание таинственно пропадает.')
continue print('Итерация номер', i, 'успешно
завершена.')print('Цикл завершён.')
Рассмотрим еще один пример:
count = 1while count < 100: if count % 5 == 0: continue
print(count) count += 1
Что будет напечатано в процессе выполнения программы?
Предполагается, что программа выведет все числа от 1 до 100, не
кратные 5. Но на самом деле, если вы запустите программу в режиме
трассировки, на экран выведется 1 2 3 4, а потом программа уйдет в
бесконечный цикл. Почему это происходит?
Когда переменная count станет равна 5, записанное в операторе if
условие станет истинным и выполнится оператор continue. Т. е. мы
немедленно перейдем к следующей итерации цикла, пропуская вывод
числа и увеличение счетчика count.
Переменная count так и не увеличится и по-прежнему останется со
значением 5. Значит, условие в if будет все так же равно True, и
цикл станет бесконечным.
Иными словами, часто использовать break и continue не рекомендуют,
поскольку они приводят к произвольному перемещению точки выполнения
программы по всему коду, что усложняет понимание и следование
логике. Тем не менее разумное использование этих операторов может
улучшить читабельность циклов в программе, уменьшив при этом
количество вложенных блоков и необходимость в сложной логике
выполнения цикла.
Например, рассмотрим следующую программу:
count = 0exitLoop = Falsewhile not exitLoop: print("Введите 'e'
для выхода и любую другую клавишу для продолжения:") sm = input()
if sm == 'e': exitLoop = True else: count += 1
print("Вы зашли в цикл ", count, " раз(а)")
А теперь ту же самую программу напишем с использованием оператора
break:
exitLoop = Falsewhile not exitLoop: print("Введите 'e' для выхода
и любую другую клавишу для продолжения:") sm = input() if sm
== 'e': break count += 1 print("Вы зашли в цикл ",
count, " раз(а)")
Чего нам удалось добиться? Во-первых, мы избежали использования как
логической переменной, так и оператора else. Уменьшение количества
используемых переменных и вложенных блоков улучшают читабельность и
понимание кода больше, чем break или continue могут нанести вред.
Вложенные циклы
Аннотация
В этом уроке мы рассмотрим вложенные циклы, позволяющие запустить
цикл внутри циклического оператора. Приведем несколько примеров
вложенности разных циклов, а также применение операторов break и
continue со вложенными циклами.

Вложенные циклы. Принцип работы


Часто бывают ситуации, когда один и тот же набор действий необходимо
выполнить несколько раз для каждого повторяющегося действия.
Например, мы уже несколько раз сталкивались с задачами, когда
программа получает от пользователя данные до сигнала остановки, —
для этого используется цикл. А теперь представьте, что после ввода
данных или числа с ними надо сделать какие-либо действия, которые
тоже требуют цикла (например, вычислить факториал), тогда нам нужен
еще один цикл, внутри первого.
Вложенные циклы
Циклы называются вложенными (т. е. один цикл находится внутри
другого), если внутри одного цикла во время каждой итерации
необходимо выполнить другой цикл. Так для каждого витка внешнего
цикла выполняются все витки внутреннего цикла. Основное требование
для таких циклов: чтобы все действия вложенного цикла располагались
внутри внешнего.
При использовании вложенных циклов стоит помнить, что изменения,
внесенные внутренним циклом в какие-либо данные, могут повлиять на
внешний.
Давайте рассмотрим следующую задачу: необходимо вывести в строку
таблицу умножения для заданного числа. Задача решается так:
k = int(input())for i in range(1, 10): print(i, '*', k, '=', k *
i, sep='', end='\t')
А если нам нужно вывести таблицу умножения для всех чисел от 1 до k?
Очевидно, что в этом случае предыдущую программу нужно повторить k
раз, где вместо k будут использоваться числа от 1 до k включительно.
Эту задачу можно записать двумя циклами, где для каждого значения
внешнего цикла будут выполняться все значения внутреннего цикла.
Программа будет выглядеть так:
k = int(input())for j in range(1, k + 1): for i in range(1, 10):
print(i, '*', j, '=', j * i, sep='', end='\t') print()
Проанализируем работу данной программы. Выполнение программы
начинается с внешнего цикла. Итератор j внешнего цикла for меняет
свое значение от начального (1) до конечного (k). Обратите внимание:
чтобы включить число k в рассматриваемый диапазон, в заголовке цикла
указавается промежуток от 1 до k + 1. Затем циклически выполняется
следующее:

 Проверяется условие j < k + 1.


 Если оно соблюдается, выполняется оператор в теле цикла, т. е.
выполняется внутренний цикл.
o Итератор i внутреннего цикла for будет изменять свои
значения от начального (1) до конечного (10), не включая
10

 Затем циклически выполняется следующее:


o Проверяется условие i < 10
o Если оно удовлетворяется, выполняется оператор в теле
цикла, т. е. оператор print(i, '*', j, '=', j * i,
sep='', end='\t'), выводящий на экран строку таблицы
умножения в соответствии с текущими значениями переменных
i и j
o Затем значение итератора i внутреннего цикла
увеличивается на единицу, и оператор внутреннего цикла
for проверяет условие i < 10. Если условие соблюдается,
выполняется тело внутреннего цикла при неизменном
значении итератора внешнего цикла до тех пор, пока
выполняется условие i < 10
o Если условие i < 10 не удовлетворяется, т. е. как только
i станет равен или больше 10, оператор тела цикла не
выполняется, внутренний цикл завершается и управление в
программе передается за пределы оператора for внутреннего
цикла, т. е. выполняется перевод строки, вызванный
использованием функции print() (строка 5), а затем
возвращается к оператору for внешнего цикла
 Значение итератора внешнего цикла j увеличивается на единицу,
и проверяется условие j < k + 1. Если условие не соблюдается,
т. е. как только j станет больше k, оператор тела цикла не
выполняется, внешний цикл завершается и управление в программе
передается за пределы оператора for внешнего цикла, т. е. в
данном случае программа завершает работу.
Таким образом, на примере печати таблицы умножения показано, что при
вложении циклов внутренний цикл выполняется полностью от начального
до конечного значения параметра при неизменном значении параметра
внешнего цикла. Затем значение параметра внешнего цикла изменяется
на единицу, и опять от начала и до конца выполняется вложенный цикл.
И так до тех пор, пока значение параметра внешнего цикла не станет
больше конечного значения, определенного в операторе for внешнего
цикла.

Графическое представление вложенных циклов


Работу циклов можно сравнить с вращением связанных шестеренок
разного размера:

Внешний цикл — это как бы большая шестеренка, за один свой оборот


(виток цикла) внешний цикл заставляет вращаться вложенный цикл
(меньшую шестеренку) несколько раз.
Обратите внимание: такая иллюстрация точна в случае, если число
повторов вложенного цикла не зависит от того, какой именно (1-й, n-й
или иной) виток делает внешний цикл, а так бывает не всегда.

Оператор break и continue во вложенных циклах


Рассмотрим другую задачу: представьте, что необходимо распечатать
все строки таблицы умножения для чисел от 1 до 10, кроме строки для
числа k.
Тогда нам нужно будет пропустить выполнение внутреннего цикла, когда
придет k-я строка.
Это можно сделать через оператор continue, который просто прервет
выполнение данного витка цикла и перейдет к следующей итерации
цикла:
k = int(input())for j in range(1, 10): if j == k: continue
for i in range(1, 10): print(i, '*', j, '=', j * i, sep='',
end='\t') print()
Важно!
Обратите внимание: если оператор break или continue расположен
внутри вложенного цикла, он действует именно на вложенный цикл, а не
на внешний. Нельзя выскочить из вложенного цикла сразу на самый
верхний уровень.
А теперь попробуйте вывести всю таблицу умножения, кроме столбца k.
Вот еще одна программа, которая использует вложенные циклы и
оператор break. Она учит пользователя вводить числа палиндромы —
программа выполняется до тех пор, пока не будет введено число
палиндром:
print('Тренажер по вводу палиндрома:')while True: print('Введите
число палиндром:') number = n = int(input()) reverse = 0
while n > 0: reverse = reverse * 10 + n % 10 n //= 10
if number == reverse: print('Вы ввели палиндром! Программа
остановлена.') break print('Введенное число не палиндром,
попробуйте еще раз.')
Множества
Аннотация
В этом уроке мы обсудим множества Python. Этот тип данных аналогичен
математическим множествам, он поддерживает быстрые операции проверки
наличия элемента в множестве, добавления и удаления элементов,
операции объединения, пересечения и вычитания множеств.

Объекты типа set


Мы написали уже много программ, работающих с данными, количество
которых неизвестно на момент написания программы. Теперь было бы
здорово уметь хранить в памяти неизвестное на момент написания
программы количество данных. В этом нам помогут так называемые
коллекции — специальные типы данных, которые умеют хранить несколько
значений под одним именем. Первая из коллекций, с которой мы
познакомимся, называется множество.
Множество
Множество — составной тип данных, представляющий собой несколько
значений (элементов множества) под одним именем. Этот тип называется
set, не создавайте, пожалуйста, переменные с таким именем! Чтобы
задать множество, нужно в фигурных скобках перечислить его элементы.
Здесь создается множество из четырех элементов (названий
млекопитающих), которое затем выводится на экран:
mammals = {'cat', 'dog', 'fox', 'elephant'}print(mammals)
Введите этот код в Python и запустите программу несколько раз.
Скорее всего, вы увидите разный порядок перечисления млекопитающих,
так происходит потому, что элементы в множестве Python не
упорядочены. Это позволяет быстро выполнять операции над
множествами, о которых мы скоро поговорим чуть позже.
Создание множества
Для создания пустых множеств обязательно вызывать функцию set:
empty = set()
Обратите внимание: элементами множества могут быть строки или числа.
Возникает вопрос: а может ли множество содержать и строки, и числа?
Давайте попробуем:
mammals_and_numbers = {'cat', 5, 'dog', 3, 'fox', 12, 'elephant',
4}print(mammals_and_numbers)
Как видим, множество может содержать и строки, и числа, а Python
опять выводит элементы множества в случайном порядке. Заметьте, если
поставить в программе оператор вывода множества на экран несколько
раз, не изменяя само множество, порядок вывода элементов не
изменится.
Может ли элемент входить в множество несколько раз? Это было бы
странно, так как совершенно непонятно, как отличить один элемент от
другого. Нет смысла хранить несколько одинаковых объектов, удобно
иметь контейнер, сохраняющий только уникальный объекты. Поэтому
множество содержит каждый элемент только один раз. Следующий
фрагмент кода это демонстрирует:
birds = {'raven', 'sparrow', 'sparrow', 'dove', 'hawk',
'falcon'}print(birds)
Важно!
Итак, у множеств есть три ключевые особенности:

 Порядок элементов в множестве не определен


 Элементы множеств — строки и/или числа
 Множество не может содержать одинаковых элементов
Выполнение этих трех свойств позволяет организовать элементы
множества в структуру со сложными взаимосвязями, благодаря которым
можно быстро проверять наличие элементов в множестве, объединять
множества и т. д. Но пока давайте обсудим ограничения.

Операции над множеством


Простейшая операция — вычисление числа элементов множества. Для
этого служит функция len. Мы уже встречались с этой функцией раньше,
когда определяли длину строки:
my_set = {'a', 'b', 'c'}n = len(my_set) # => 3
Далее можно вывести элементы множества с помощью функции print:
my_set = {'a', 'b', 'c'}print(my_set) # => {'b', 'c', 'a'}
В вашем случае порядок может отличаться, так как правило
упорядочивания элементов в множестве выбирается случайным образом
при запуске интерпретатора Python.
Очень часто необходимо обойти все элементы множества в цикле. Для
этого используется цикл for и оператор in, с помощью которых можно
перебрать не только все элементы диапазона (как мы это делали
раньше, используя range), но и элементы множества:
my_set = {'a', 'b', 'c'}for elem in my_set: print(elem)
такой код выводит:
bac
Однако, как и в прошлый раз, в вашем случае порядок может
отличаться: заранее он неизвестен. Код для работы с множествами
нужно писать таким образом, чтобы он правильно работал при любом
порядке обхода. Для этого надо знать два правила:

 Если мы не изменяли множество, порядок обхода элементов тоже


не изменится
 После изменения множества порядок элементов может измениться
произвольным образом
Чтобы проверить наличие элемента в множестве, можно воспользоваться
уже знакомым оператором in:
if elem in my_set: print('Элемент есть в множестве')else:
print('Элемента нет в множестве')
Выражение elem in my_set возвращает True, если элемент есть в
множестве, и False, если его нет. Интересно, что эта операция для
множеств в Python выполняется за время, не зависящее от мощности
множества (количества его элементов).
Добавление элемента в множество делается при помощи add:
new_elem = 'e'my_set.add(new_elem)
add — что-то вроде функции, «приклеенной» к конкретному множеству.
Такие «приклеенные функции» называются методами.
Таким образом, если в коде присутствует имя множества, затем точка и
еще одно название со скобками, второе название — имя метода. Если
элемент, равный new_elem, уже существует в множестве, оно не
изменится, поскольку не может содержать одинаковых элементов. Ошибки
при этом не произойдет. Небольшой пример:
my_set =
set()my_set.add('a')my_set.add('b')my_set.add('a')print(my_set)
Данный код три раза вызовет метод add, «приклеенный» к множеству
my_set, а затем выведет либо {'a', 'b'}, либо {'b', 'a'}.
С удалением элемента сложнее. Для этого есть сразу три метода:
discard (удалить заданный элемент, если он есть в множестве, и
ничего не делать, если его нет), remove (удалить заданный элемент,
если он есть, и породить ошибку KeyError, если нет) и pop. Метод pop
удаляет некоторый элемент из множества и возвращает его как
результат. Порядок удаления при этом неизвестен.
my_set = {'a', 'b', 'c'} my_set.discard('a') #
Удалёнmy_set.discard('hello') # Не удалён, ошибки
нетmy_set.remove('b') # Удалёнprint(my_set) #
В множестве остался один элемент 'c'my_set.remove('world') # Не
удалён, ошибка KeyError
На первый взгляд, странно, что есть метод remove, который
увеличивает количество падений вашей программы. Однако если вы на
100 % уверены, что элемент должен быть в множестве, то лучше
получить ошибку во время отладки и исправить ее, чем тратить время
на поиски при неправильной работе программы.
Метод pop удаляет из множества случайный элемент и возвращает его
значение:
my_set = {'a', 'b', 'c'}print('до удаления:', my_set)elem =
my_set.pop()print('удалённый элемент:', elem)print('после
удаления:', my_set)
Результат работы случаен, например, такой код может вывести
следующее:
до удаления: {'b', 'a', 'c'}удалённый элемент: bпосле удаления:
{'a', 'c'}
Если попытаться применить pop к пустому множеству, произойдет ошибка
KeyError.
Очистить множество от всех элементов можно методом clear:
my_set.clear()

Операции над двумя множествами


Есть четыре операции, которые из двух множеств делают новое
множество: объединение, пересечение, разность и симметричная
разность.

Объединение двух множеств включает в себя все элементы, которые есть


хотя бы в одном из них. Для этой операции существует метод union:
union = my_set1.union(my_set2)
Или можно использовать оператор |:
union = my_set1 | my_set2

Пересечение двух множеств включает в себя все элементы, которые есть


в обоих множествах:
intersection = my_set1.intersection(my_set2)
Или аналог:
intersection = my_set1 & my_set2

Разность двух множеств включает в себя все элементы, которые есть в


первом множестве, но которых нет во втором:
diff = my_set1.difference(my_set2)
Или аналог:
diff = my_set1 - my_set2

Симметричная разность двух множеств включает в себя все элементы,


которые есть только в одном из этих множеств:
symm_diff = my_set1.symmetric_difference(my_set2)
Или аналогичный вариант:
symm_diff = my_set1 ^ my_set2
Люди часто путают обозначения | и &, поэтому рекомендуется вместо
них писать s1.union(s2) и s1.intersection(s2). Операции − и ^
перепутать сложнее, их можно записывать прямо так.
s1 = {'a', 'b', 'c'}s2 = {'a', 'c', 'd'}union = s1.union(s2)
# {'a', 'b', 'c', 'd'}intersection = s1.intersection(s2) # {'a',
'c'}diff = s1 - s2 # {'b'}symm_diff = s1 ^ s2
# {'b', 'd'}

Сравнение множеств
Все операторы сравнения множеств, а именно: ==, <, >, <=, >=,
возвращают True, если сравнение истинно, и False — в противном
случае.
Равенство и неравенство множеств
Множества считаются равными, если они содержат одинаковые наборы
элементов. Равенство множеств, как в случае с числами и строками,
обозначается оператором ==.
Неравенство множеств обозначается оператором !=. Он работает
противоположно оператору ==.
if set1 == set2: print('Множества равны')else:
print('Множества не равны')
Обратите внимание на то, что у двух равных множеств могут быть
разные порядки обхода, например, из-за того, что элементы в каждое
из них добавлялись в разном порядке.
Теперь перейдем к операторам <=, >=. Они означают «является
подмножеством» и «является надмножеством».
Подмножество и надмножество
Подмножество — некоторая выборка элементов множества, которая может
быть как меньше множества, так и совпадать с ним, на что указывают
символы «<» и «=» в операторе <=. Наоборот, надмножество включает
все элементы некоторого множества и, возможно, какие-то еще.
s1 = {'a', 'b', 'c'}print(s1 <= s1) # True s2 = {'a', 'b'}print(s2
<= s1) # Trues3 = {'a'}print(s3 <= s1) # Trues4 = {'a',
'z'}print(s4 <= s1) # False
Операция s1 < s2 означает «s1 является подмножеством s2, но целиком
не совпадает с ним». Операция s1 > s2 означает «s1 является
надмножеством s2, но целиком не совпадает с ним».
Строки. Индексация
Аннотация
На этом занятии мы углубим свои знания о строках. Теперь мы сможем
не только считывать строку, но и работать с ней, в том числе делать
посимвольный перебор.

Строка как коллекция


На прошлом занятии мы познакомились с коллекцией, которая называется
множество. Вспомним, что основная особенность коллекций —
возможность хранить несколько значений под одним именем. Можно
сказать, что коллекция является контейнером для этих значений.
Но еще до изучения множеств мы уже знали тип данных, который ведет
себя подобно коллекции. Этот тип данных — строка. Действительно,
ведь строка фактически является последовательностью символов. В
некоторых языках программирования есть специальный тип данных char,
позволяющий хранить один символ. В Python такого типа данных нет,
поэтому можно сказать, что строка — последовательность
односимвольных строк.

Что мы знаем о строках


Давайте вспомним, что мы уже знаем о работе со строками в языке
Python. Мы умеем создавать строки четырьмя способами: задавать
напрямую, считывать с клавиатуры функцией input(), преобразовывать
число в строку функцией str и склеивать из двух других строк
операцией +. Кроме того, мы умеем узнавать длину строки, используя
функцию len, и проверять, является ли одна строка частью другой,
используя операцию in:
fixed_word = 'опять'print(fixed_word)word = input()print(word)number
= 25number_string = str(number)print(number_string)word_plus_number
= fixed_word +
number_stringprint(word_plus_number)print(len(word_plus_number))prin
t('оп' in word_plus_number)

Индексация в строках
В отличие от множеств, в строках важен порядок элементов (символов).
Действительно, если множества {1, 2, 3} и {3, 2, 1} — это одинаковые
множества, то строки МИР и РИМ — две совершенно разные строки.
Наличие порядка дает нам возможность пронумеровать символы.
Нумерация символов начинается с 0:

Индекс
По индексу можно получить соответствующий ему символ строки. Для
этого нужно после самой строки написать в квадратных скобках индекс
символа.
word = 'привет'initial_letter = word[0]print(initial_letter) #
сделает то же, что print('п')other_letter =
word[3]print(other_letter) # сделает то же, что print('в')
Естественно, в этом примере word с тем же успехом можно было считать
с клавиатуры через input(). Тогда мы не могли бы заранее сказать,
чему равны переменные initial_letter и other_letter.
А что будет, если попытаться получить букву, номер которой слишком
велик? В этом случае Python выдаст ошибку:
word = 'привет'print(word[6]) # builtins.IndexError: string index
out of range
Конечно, номер в квадратных скобках — не всегда фиксированное число,
которое прописано в самой программе. Его тоже можно считать с
клавиатуры или получить в результате арифметического действия.
word = 'привет'number_of_letter = int(input()) # предположим,
пользователь ввел 3print(word[number_of_letter]) # тогда будет
выведена буква 'в'
Отрицательные индексы
Кроме «прямой» индексации (начинающейся с 0), в Python разрешены
отрицательные индексы: word[-1] означает последний символ строки
word, word[-2] — предпоследний и т д.

А можно ли, используя индексацию, изменить какой-либо символ строки?


Давайте проверим:
word = 'карова' # Написали слово с ошибкойword[1] = 'о' #
Пробуем исправить, но:# TypeError: 'str' object does not support
item assignment
Важно!
Интерпретатор Python выдает ошибку — значит, изменить отдельный
символ строки невозможно, т. е. строка относится к неизменяемым
типам данных в Python.

Перебор элементов строки


В предыдущем уроке мы узнали, что цикл for можно использовать для
перебора элементов множества. Таким же образом можно использовать
цикл for, чтобы перебрать все буквы в слове:
text = 'hello, my dear friends!'vowels = 0for letter in text: if
letter in {'a', 'e', 'i', 'o', 'u', 'y'}: vowels +=
1print(vowels)
Но, так как символы в строке пронумерованы, у нас есть еще один
способ перебрать все элементы в строке: перебрать все индексы,
используя уже знакомую нам конструкцию for i in range(...).
text = 'hello, my dear friends!'vowels = 0for i in range(len(text)):
if text[i] in 'aeiouy': vowels += 1print(vowels)

Хранение текстов в памяти компьютера


Давайте немного поговорим о том, как строки хранятся в памяти
компьютера.
Кодирование
Поскольку компьютер умеет хранить только двоичные числа, для записи
нечисловой информации (текстов, изображений, видео, документов)
прибегают к кодированию.
Самый простой случай кодирования — сопоставление кодов текстовым
символам.
Один самых распространенных форматов такого кодирования — таблица
ASCII (American standard code for information interchange).

Изначально в этой таблице каждому символу был поставлен в


соответствие 7-битный код, что позволяло идентифицировать 128
различных символов. В таблице вы не видите символы с кодами,
меньшими 32, так как они являются служебными и не предназначены для
непосредственного вывода на экран (пробел, перевод строки, табуляция
и т. д.).
Этого хватало на латинские буквы обоих регистров, знаки препинания и
спецсимволы — например, перевод строки или разрыв страницы. Позже
код расширили до 1 байта, что позволяло хранить уже 256 различных
значений: в таблицу помещались буквы второго алфавита (например,
кириллица) и дополнительные графические элементы (псевдографика).
В некоторых относительно низкоуровневых языках (например, в С) можно
в любой момент перейти от представления строки в памяти к
последовательности байтов, начинающейся по какому-либо адресу.
Сейчас однобайтные кодировки отошли на второй план, уступив место
Юникоду.
Юникод
Юникод — таблица, которая содержит соответствия между числом и
каким-либо знаком, причем количество знаков может быть любым. Это
позволяет одновременно использовать любые символы любых алфавитов и
дополнительные графические элементы. Кроме того, в Юникоде каждый
символ, помимо кода, имеет некоторые свойства: например, буква это
или цифра. Это позволяет более гибко работать с текстами.
В Юникод все время добавляются новые элементы, а сам размер этой
таблицы не ограничен и будет только расти, поэтому сейчас при
хранении в памяти одного юникод-символа может потребоваться от 1 до
8 байт. Отсутствие ограничений привело к тому, что стали появляться
символы на все случаи жизни. Например, есть несколько снеговиков.

Этого вы можете увидеть, если наберете:


print('\u2603')☃
Важно понять, что все строки в Python хранятся именно как
последовательность юникод-символов.
Функция ord
Для того чтобы узнать код некоторого символа, существует функция ord
(от order — «порядок»).
ord('Б') 1041
Функция chr
Зная код, всегда можно получить соответствующий ему символ. Для
этого существует функция chr (от character — «символ»):
chr(1041) 'Б'
Функции ord и chr часто работают в паре. Попробуйте, например,
предположить, что будет выведено на экран в результате работы
следующей программы:
for i in range(26): print(chr(ord('A') + i))
Строки. Срезы
Аннотация
На этом занятии мы продолжим отрабатывать навыки работы со строкой и
познакомимся с новым методом извлечения подстроки — срезами.

Работа со строками (повторение)


Рассмотрим еще одну задачу. Билет называют счастливым по-питерски,
если сумма цифр его номера, стоящих на четных местах, равна сумме
цифр, стоящих на нечетных местах. Нам необходимо написать программу,
которая определяет, является ли билет счастливым по-питерски.

Если рассматривать номер билета как строку из цифр, задача сводится


к подсчету суммы цифр, стоящих на позициях 0, 2, 4..., и суммы цифр,
стоящих на позициях 1, 3, 5... Чтобы перебрать элементы, мы можем
воспользоваться конструкцией for i in range(...), указав шаг 2.
Тогда соответствующий фрагмент программы может выглядеть следующим
образом:
number = input()odd = even = 0for i in range(0, len(number), 2):
odd += int(number[i])for i in range(1, len(number), 2): even +=
int(number[i])if odd == even: print('Счастливый по-питерски!')
Подумайте, как можно решить данную задачу за один цикл.

Срезы строк
На примере разобранной задачи мы увидели, что перебор элементов
строки с помощью конструкции for i in range(...) является достаточно
гибким: можно перебрать не все индексы, можно идти с шагом, скажем,
2 или даже −1, то есть в обратном порядке. Но существует способ без
всякого цикла преобразовать строку нужным образом: взять отдельный
ее кусок, символы с нечетными номерами и т. д. Этот способ — срез
(slice).
Срез строки
В самом простом варианте срез строки — ее кусок от одного индекса
включительно и до другого не включительно (как для range). То есть
это новая, более короткая строка.
Срез записывается с помощью квадратных скобок, в которых указывается
начальный и конечный индекс, разделенные двоеточием.
text = 'Hello, world!'print(text[0:5])print(text[7:12])
Если не указан начальный индекс, срез берется от начала (от 0). Если
не указан конечный индекс, срез берется до конца строки. Попробуйте
предположить, что будет выведено на экран, если в предыдущей
программе записать срезы следующим образом:
text = 'Hello, world!'print(text[:5])print(text[7:])
Разрешены отрицательные индексы для отсчета с конца списка. В
следующем примере из строки, содержащей фамилию, имя и отчество,
будет извлекаться фамилия.
full_name = 'Иванов И. И.'surname = full_name[:-6]
Как и для range, в параметры среза можно добавить третье число — шаг
обхода. Этот параметр не является обязательным и записывается через
второе двоеточие. Вот как может выглядеть программа «Счастливый
билет», если решать ее с помощью срезов:
number = input()odd = even = 0# срез будет от начала строки до конца
с шагом два: 0, 2, 4,... for n in number[::2]: odd += int(n)#
срез от второго элемента строки до конца с шагом два: 1, 3, 5,...for
n in number[1::2]: even += int(n)if odd == even:
print('Счастливый по-питерски!')
Интересное отличие среза от обращения по индексу к отдельному
элементу состоит в том, что мы не получим ошибку при указании границ
среза за пределами строки. В срез в таком случае попадут только те
элементы, которые находятся по валидным индексам среза:
a = 'Python'print(a[2:10000]) # thonprint(a[999:]) # пустая строка
Шаг может быть и отрицательным — для прохода по строке в обратном
порядке. Если в этом случае не указать начальный и конечный индекс
среза, ими станут последний и первый индексы строки соответственно
(а не наоборот, как при положительном шаге):
text = 'СЕЛ В ОЗЕРЕ БЕРЕЗОВ ЛЕС'text_reversed = text[::-1]print(text
== text_reversed)
Итак, с помощью квадратных скобок можно получить доступ как к одному
символу строки, так и к некоторой последовательности символов,
причем совсем необязательно идущих подряд!
Знакомство со списками
Аннотация
В уроке рассматривается новый тип данных — списки (list), обращение
к элементам списка по индексу (аналогично строкам, но с возможностью
изменения элементов списка), метод append и вопросы перебора
элементов списка и срезов списка.

Списки
Мы уже знаем тип данных, который называется множество и является
коллекцией (контейнером), то есть позволяет хранить несколько
элементов данных, и тип, который тоже обладает свойствами коллекции
и называется строка. Сегодня мы познакомимся с еще одним типом-
коллекцией, который называется список (list). Никогда не создавайте
переменные с таким именем!
Списки
Списки являются очень гибкой структурой данных и широко используются
в программах. Давайте рассмотрим основные свойства списка в
сравнении с теми коллекциями, которые мы уже знаем:

 Список хранит несколько элементов под одним именем (как и


множество)
 Элементы списка могут повторяться (в отличие от множества)
 Элементы списка упорядочены и проиндексированы, доступна
операция среза (как в строке)
 Элементы списка можно изменять (в отличие от строки)
 Элементами списка могут быть значения любого типа: целые и
действительные числа, строки и даже другие списки

Создание списков
Чтобы работать со списком, нужно его создать. Для этого используется
операция присваивания.
Создание списка
Чтобы задать готовый список, нужно справа от знака присваивания в
квадратных скобках перечислить его элементы через запятую. Здесь
создается список из первых пяти простых чисел, который помещается в
переменную primes («простые числа»):
primes = [2, 3, 5, 7, 11]print(primes) # выводим на экран список
целиком
Для того чтобы создать пустой список, можно воспользоваться
конструкцией [] или функцией list.
empt1 = [] # это пустой списокempt2 = list() # и это тоже пустой
список
Теперь вспомним один из рассмотренных нами ранее способов создания
cтроки из заданного количества повторяющихся подстрок. Такую строку
можно легко составить путем умножения на число:
print("'$' * 5 -->", '$' * 5)print("'-|' * 4 + '-' -->", '-|' * 4 +
'-')'$' * 5 --> $$$$$'-|' * 4 + '-' --> -|-|-|-|-
Аналогично поступают и со списками:
print([2, 3] * 4) [2, 3, 2, 3, 2, 3, 2, 3]
Важно!
Для генерации списков и строк, состоящих строго из повторяющихся
элементов (например, список из заданного количества нулей),
умножение на число — самый короткий и красивый метод.
my_list = [0] * 4

Индексация в списках
Чтобы получить отдельный элемент списка, нужно записать после него
(или имени переменой, связанной с данным списком) в квадратных
скобках номер (индекс) нужного элемента. Индекс отсчитывается с
нуля, как в строках. Так же, как и в строках, для нумерации с конца
разрешены отрицательные индексы.
Таким образом, мы умеем использовать квадратные скобки в Python уже
для трех вещей: задания нового списка (тогда внутри этих скобок
перечисляются его элементы), получения элемента списка или строки по
индексу (тогда в скобках указывается индекс) и получения среза
строки.
print('Сумма первых двух простых чисел:', primes[0] +
primes[1])print('Последнее из простых чисел в нашем списке:',
primes[-1])
Как и в строках, попытка обратиться к элементу с несуществующим
индексом вызовет ошибку:
print(primes[5]) # ошибка: index out of range

Добавление элемента в список


Добавление элемента в конец списка делается при помощи метода append
(этот метод аналогичен методу add, используемому для добавления
элементов в множество):
primes.append(13)primes.append(15) # ой, ошиблись — 15 составное
число!
Обратите внимание: для того чтобы воспользоваться методом append,
нужно, чтобы список был создан (при этом он может быть пустым).
Важно!
Попытка применить метод append к несуществующему списку приведет к
ошибке. Заметьте: два вызова метода append в следующем примере
добавляют элемент к двум разным спискам.
odd_numbers = [1, 3, 5, 7, 9, 11, 13, 15,
17]primes.append(19)odd_numbers.append(19)
Кроме того, вы можете расширить имеющийся список любым итерабельным
(перечисляемым) объектом с помощью метода extend:
my_list = [1, 2, 3]another_list = [4, 5,
6]my_list.extend(another_list)print(my_list)[1, 2, 3, 4, 5, 6]
Расширение списка строкой
Имейте в виду, что строка является итерируемой, поэтому, если вы
расширите список строкой, вы добавите каждый символ, когда будете
перебирать строку (что может быть не так, как вы хотите):
my_list = [1, 2, 3]another_list =
"привет"my_list.extend(another_list)print(my_list) # [1, 2, 3, 'п',
'р', 'и', 'в', 'е', 'т']
Расширение списка множеством
Множество также является итерируемым типом, поэтому если расширить
список множеством, то элементы множества добавятся в конец списка,
но в произвольном порядке:
my_list = [1, 2, 3]another_set = {'п', 'р', 'и', 'в', 'е',
'т'}my_list.extend(another_set)print(my_list) # [1, 2, 3, 'в', 'и',
'р', 'т', 'е', 'п']
Изменение элемента списка
В отличие от отдельных символов в строках, элемент списка можно
поместить слева от "=" в операторе присваивания и тем самым изменить
этот элемент:
primes[6] = 17 # Исправляем ошибку:# седьмое (нумерация элементов
списка - с нуля!)# простое число - не 15, а 17.
Тем не менее многие вещи, которые можно делать со строками, можно
делать и со списками:
print(len(primes)) # выводим длину спискаprimes += [23, 29] #
списки можно складывать, как и строкиprint(primes) # выведет [2, 3,
5, 7, 11, 13, 17, 19, 23, 29]if 1 in primes: # можно проверять,
содержится ли в списке элемент print('Мы считаем единицу простым
числом.')else: print('Мы, как и всё остальное человечество, не
считаем 1 простым числом.')

Перебор элементов списка


Во время выполнения программы текущее количество элементов списка
всегда известно. Поэтому, если нужно что-то сделать с каждым
элементом списка (например, напечатать его на экране), можно
перебрать элементы с помощью цикла for. При этом, как и для строк,
возможны два варианта перебора — перебор индексов и перебор самих
элементов.
for i in range(len(primes)): # выведем по очереди все элементы
списка... print('Простое число номер', i + 1, '-', primes[i])for
p in primes: print('Квадрат числа', p, '-', p ** 2) # и их
квадраты
Заметьте, что при использовании конструкции for i in
range(len(имя_списка)) индексы перебираются в цикле очень удобно: от
0 включительно до длины списка не включительно. Таким образом, можно
перебрать все элементы списка.
Цикл for нередко используется и для формирования списка, если мы
заранее знаем, сколько элементов в нем должно быть:
n = 10a = []print('Введите', n, 'значений:')for i in range(n):
a.append(input())print('Получился список строк:', a)

Срезы списков
Как и для строк, для списков определена операция взятия среза:
months = ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь',
'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь',
'декабрь']spring = months[2:5] # spring == ['март', 'апрель',
'май']for month in spring: print(month)
Использование срезов
Срезы можно использовать и для присваивания новых значений элементам
списка. Например, если мы решим перевести на английский названия
летних месяцев, это можно сделать с помощью среза:
months[5:8] = ['June', 'July', 'August']
Теперь список months будет выглядеть так: ['январь', 'февраль',
'март', 'апрель', 'май', 'June', 'July', 'August', 'сентябрь',
'октябрь', 'ноябрь', 'декабрь'].
Удаление элементов
С помощью функции del можно удалять элементы списка.
a = [1, 2, 3, 4, 5, 6]del a[2]print(a)[1, 2, 4, 5, 6]
Элемент под указанным индексом удаляется, а список перестраивается.
Функция del работает и со срезами: например, так можно удалить все
элементы на четных позициях исходного списка:
a = [1, 2, 3, 4, 5, 6]del a[::2]print(a)[2, 4, 6]

Списки и массивы
Во многих языках программирования (да и в самом Python, в недрах
стандартной библиотеки) имеется другой тип данных с похожими
свойствами — массив. Поэтому списки иногда называют массивами, хоть
это и не совсем правильно.
Важно!
Элементы массива имеют одинаковый тип и располагаются в памяти одним
куском, а элементы списка могут быть разбросаны по памяти как угодно
и могут иметь разный тип. Все это замедляет работу списков по
сравнению с массивами, но придает им гораздо большую гибкость. Из
этого различия вытекает и «питонский путь» формирования списка: не
создавать «пустой массив» и заполнять его значениями, а append’ить
значения к изначально пустому списку.
Кортежи. Преобразование коллекций
Аннотация
В уроке вводится еще один контейнер — кортеж (tuple). Более подробно
рассматривается операция присваивания кортежей, знакомая нам по
конструкции a, b = b, a, и применение этой операции в реализации
классического алгоритма — сортировки пузырьком. Рассматриваются и
вопросы преобразования одной коллекции в другую.

Кортежи
Мы уже знаем такие коллекции, как списки, множества и строки.
Сегодня мы рассмотрим еще один тип данных, являющийся коллекцией,
который называется tuple (читается «тюпл» или «тьюпл», а переводится
как «кортеж»).
Кортежи
Кортежи очень похожи на списки, они тоже являются индексированной
коллекцией, только вместо квадратных в них используются круглые
скобки (причем их часто можно пропускать):
# кортеж из двух элементов; тип элементов может быть любойcard =
('7', 'пик') # пустой кортеж (из 0
элементов)empty = () # кортеж из 1 элемента - запятая нужна, чтобы
отличить от обычных скобокt = (18,)# длина, значение отдельного
элемента, сложение - как у списковprint(len(card), card[0], card +
t)
Кортежи можно сравнивать между собой:
(1, 2) == (1, 3) # False(1, 2) < (1, 3) # True(1, 2) < (5,)
# True('7', 'червей') < ('7', 'треф') # False# А вот так
сравнивать нельзя: элементы кортежей разных типов(1, 2) < ('7',
'пик')
Обратите внимание: операции == и != применимы к любым кортежам,
независимо от типов элементов. А вот операции <, >, <=, >= применимы
только в том случае, когда соответствующие элементы кортежей имеют
один тип. Поэтому сравнивать ('7', 'червей') и ('7', 'треф') можно,
а вот кортежи (1, 2) и ('7', 'пик') нельзя — интерпретатор Python
выдаст ошибку. При этом сравнение происходит последовательно элемент
за элементом, а если элементы равны — просматривается следующий
элемент.
Неизменяемость
Важнейшее техническое отличие кортежей от списков — неизменяемость.
Как и к строке, к кортежу нельзя добавить элемент методом append, а
существующий элемент нельзя изменить, обратившись к нему по индексу.
Это выглядит недостатком, но в дальнейшем мы поймем, что у кортежей
есть и преимущества.
Есть и семантическое, то есть смысловое, отличие. Если списки
предназначены скорее для объединения неопределенного количества
однородных сущностей, то кортеж — быстрый способ объединить под
одним именем несколько разнородных объектов, имеющих различный
смысл.
Так, в примере выше кортеж card состоит из двух элементов,
означающих достоинство карты и ее масть.
Еще одним приятным отличием кортежей от списков является то, что они
могут быть элементами множества:
a = {('7', 'червей'), ('7', 'треф')}print(a) # -> {('7', 'треф'),
('7', 'червей')}

Присваивание кортежей
Кортежи можно присваивать друг другу. Именно благодаря этому
работает красивая особенность Python — уже знакомая нам конструкция
вида a, b = b, a.
Как известно, по левую сторону от знака присваивания = должно стоять
имя переменной либо имя списка с индексом или несколькими индексами.
Они указывают, куда можно «положить» значение, записанное справа от
знака присваивания. Однако слева от знака присваивания можно
записать еще и кортеж из таких обозначений (грубо говоря, имен
переменных), а справа — кортеж из значений, которые следует в них
поместить. Значения справа указываются в том же порядке, что и
переменные слева (здесь скобки вокруг кортежа необязательны):
n, s = 10, 'hello'# то же самое, чтоn = 10s = 'hello'
В примере выше мы изготовили кортеж, стоящий справа от =, прямо на
этой же строчке. Но можно заготовить его и заранее:
cards = [('7', 'пик'), ('Д', 'треф'), ('Т', 'пик')]value, suit =
cards[0]print('Достоинство карты:', value)print('Масть карты:',
suit)
Самое приятное: сначала вычисляются все значения справа, и лишь
затем они кладутся в левую часть оператора присваивания. Поэтому
можно, например, поменять местами значения переменных a и b,
написав: a, b = b, a.
a, b = 1, 2 # теперь a == 1 and b == 2a, b = b, a # теперь a == 2
and b == 1
Пример ниже выведет «1 2 3». Убедитесь, что вы понимаете, почему
так.
# кручу-верчуa, b, с = 3, 2, 1b, a, c = c, a, bprint(b, c, a)
С использованием кортежей многие алгоритмы приобретают волшебную
краткость. Например, вычисление чисел Фибоначчи:
n = int(input())f1, f2 = 0, 1for i in range(n): print(f2) f1,
f2 = f2, f1 + f2

Сортировка пузырьком
Итак, у нас есть удобный способ поменять местами значения двух
переменных. Теперь рассмотрим алгоритм, в котором эта операция
играет важную роль.
Часто бывает нужно, чтобы данные не просто содержались в списке, а
были отсортированы (например, по возрастанию), то есть чтобы каждый
следующий элемент списка был не меньше предыдущего. В качестве
данных могут выступать числа или строки. Скажем, отсортированный
список [4, 1, 9, 3, 1] примет вид [1, 1, 3, 4, 9]. Конечно, для
этого есть стандартные функции и методы, но как они работают?
Классический алгоритм сортировки — сортировка пузырьком (по-научному
— сортировка обменом). Она называется так потому, что элементы
последовательно «всплывают» (отправляются в конец списка), как
пузырьки воздуха в воде. Сначала всплывает самый большой элемент, за
ним — следующий по старшинству и т. д. Для этого мы сравниваем по
очереди все соседние пары и при необходимости меняем элементы
местами, ставя больший элемент на более старшее место.
Идею наглядно объясняет венгерский народный танец:
А полный код программы, которая считывает, сортирует и выводит
список, выглядит, например, так:
n = int(input()) # количество элементовa = []for i in range(n):
# считываем элементы списка a.append(int(input()))# Сортировка
пузырьком:for i in range(n - 1): for j in range(n - 1 - i):
if a[j] > a[j + 1]: a[j], a[j + 1] = a[j + 1],
a[j]print(a)

Преобразования между коллекциями


Итак, на данный момент мы знаем уже четыре вида коллекций: строки,
списки, множества и кортежи. У вас может возникнуть вопрос: можно ли
из одной коллекции сделать другую? Например, преобразовать строку в
список или во множество? Конечно, да, для этого можно использовать
функции list, set и tuple. Если в качестве аргумента передать этим
функциям какую-либо коллекцию, новая коллекция будет создана на ее
основе.
Зачем нужно преобразование коллекций?
Преобразование строки в список позволяет получить список символов. В
некоторых задачах это может быть полезно: например, если мы хотим
изменить один символ строки:
s = 'симпотичный' # Написали с ошибкойa = list(s) # a ==
['с', 'и', 'м', 'п', 'о', 'т', 'и,' 'ч', 'н', 'ы', 'й']a[4] = 'а'
# a == ['с', 'и', 'м', 'п', 'а', 'т', 'и,' 'ч', 'н', 'ы', 'й']
С этой же целью может потребоваться преобразование кортежа в список:
# В кортеже (писатель, дата рождения) допущена ошибкаwriter = ('Лев
Толстой', 1827)a = list(writer) # a == ['Лев
Толстой', 1827]a[1] = 1828 # a == ['Лев
Толстой', 1828]
Преобразование списка или строки во множество позволяет получить
очень интересные результаты. Как вы помните, все элементы множества
должны быть уникальны, поэтому при преобразовании списка во
множество каждый элемент останется только в одном экземпляре. Таким
образом, можно очень легко убрать повторяющиеся элементы и узнать,
сколько элементов встречается в списке хотя бы один раз:
a = [1, 2, 1, 1, 2, 2, 3, 3]print('Количество элементов в списке без
повторений: ', len(set(a)))
Таким же образом можно получить все буквы без повторений, которые
встречаются в строке:
a =
set("Тетрагидропиранилциклопентилтетрагидропиридопиридиновые")print(
a, len(a)){'л', 'н', 'в', 'о', 'и', 'ц', 'п', 'т', 'Т', 'г', 'ы',
'а', 'д', 'к', 'р', 'е'} 16
Преобразование множества в список тоже возможно, но при этом нужно
учитывать, что элементы множества не упорядочены и при
преобразовании множества в список порядок элементов в нем
предсказать заранее не всегда возможно:
names = {'Иван', 'Петр', 'Сергей', 'Алексей'}print(list(names))#
Возможные варианты вывода на экран - ['Сергей', 'Алексей', 'Иван',
'Петр'], # ['Сергей', 'Петр', 'Иван', 'Алексей'], ['Алексей',
'Иван', 'Петр', 'Сергей'] # и так далее.
Методы split и join. Списочные выражения
Аннотация
В этом уроке рассматриваются два очень популярных метода строк —
split и join. Во второй части рассматриваются списочные выражения
(python list comprehensions [... for ... in ...]), которые в
сочетании с методом split позволяют, например, считывать из
стандартного потока ввода несколько значений одной строкой.

Методы split и join


Изучая множества и списки, мы уже неоднократно встречались с
методами — функциями, «приклеенными» к объекту (списку или
множеству) и изменяющими его содержимое.
Методы есть не только у списков и множеств, но и у строк. Сегодня мы
изучим два очень полезных метода строк — split и join. Они
противоположны по смыслу: split разбивает строку по произвольному
разделителю на список «слов», а join собирает из списка слов единую
строку через заданный разделитель.
Чтобы вызвать эти методы, необходимо использовать уже знакомый нам
синтаксис. После имени переменной, содержащей объект-строку, или
просто после строки через точку пишется имя метода, затем в круглых
скобках указываются аргументы. split и join, в отличие, например, от
метода списков append или метода множеств add, не изменяют объект,
которому принадлежат, а создают новый (список или строку) и
возвращают его, как это делают обычные функции типа len.
Метод split
Метод split можно вызвать вообще без аргументов или с одним
аргументом-строкой. В первом случае строка разбивается на части,
разделенные любыми символами пустого пространства (набором пробелов,
символом табуляции и т. д.). Во втором случае разделителем слов
считается строка-аргумент. Из получившихся слов формируется список.
В этом примере все сравнения истинны, т. е. все вызовы функции print
выведут True.
s = 'раз два три'print(s.split() == ['раз', 'два', 'три'])print('
one two three '.split() == ['one', 'two',
'three'])print('192.168.1.1'.split('.') == ['192', '168', '1',
'1'])print(s.split('а') == ['р', 'з дв', '
три'])print('A##B##C'.split('##') == ['A', 'B',
'C'])TrueTrueTrueTrueTrue
Метод join
join же всегда принимает один аргумент — список слов, которые нужно
склеить. Разделителем (точнее, «соединителем») служит та самая
строка, чей метод join вызывается. Это может быть и пустая строка, и
пробел, и символ новой строки, и что угодно еще. В этих примерах все
сравнения тоже истинны и каждый print выведет True.
s = ['Тот', 'Кого', 'Нельзя', 'Называть']print(''.join(s) ==
'ТотКогоНельзяНазывать')print(' '.join(s) == 'Тот Кого Нельзя
Называть')print('-'.join(s) == 'Тот-Кого-Нельзя-Называть')print('!
'.join(s) == 'Тот! Кого! Нельзя! Называть')TrueTrueTrueTrue
Итак, split служит для преобразования строки в список, а join — для
преобразования списка в строку:

Обратите внимание: split и join — методы строк. Попытка вызвать


такой метод у объекта, не являющегося строкой, вызовет ошибку!
Например, если попытаться написать заведомо бессмысленное, с точки
зрения интерпретатора Python, выражение:
[1, 2, 3].join([4, 5, 6])AttributeError Traceback
(most recent call last)<ipython-input-3-404b5f4d9169> in
<module>()----> 1 [1, 2, 3].join([4, 5, 6])AttributeError: 'list'
object has no attribute 'join'
Как видно, указан тип объекта ([1, 2, 3] — список, list) и имя
отсутствующего у него метода — join, который мы пытаемся вызвать.

Списочные выражения
Списочные выражения
Для генерации списков из неповторяющихся элементов в Python имеется
удобная синтаксическая конструкция — списочное выражение (list
comprehension). Она позволяет создавать элементы списка в цикле for,
не записывая цикл целиком.
Например, если нам необходимо создать список квадратов целых чисел
от 0 до 9 включительно, мы можем записать следующий код:
squares = []for i in range(10): squares.append(i **
2)print(squares)[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
То же самое, но гораздо короче можно сделать с помощью списочного
выражения:
squares = [i ** 2 for i in range(10)]print(squares)[0, 1, 4, 9, 16,
25, 36, 49, 64, 81]
А если нам необходимы квадраты не всех чисел, а только четных? Тогда
можно добавить условие:
even_squares = []for i in range(10): if i % 2 == 0:
even_squares.append(i ** 2)print(even_squares)[0, 4, 16, 36, 64]
То же самое, но короче, с помощью списочного выражения:
even_squares = [i ** 2 for i in range(10) if i % 2 ==
0]print(even_squares)[0, 4, 16, 36, 64]
На рисунке показано соответствие между кодом заполнения списка с
помощью цикла for и списочным выражением:

В списочном выражении можно пройти по двум или более циклам:


print([i * j for i in range(3) for j in range(3)]) [0, 0, 0, 0, 1,
2, 0, 2, 4]
На самом деле квадратные скобки не являются неотъемлемой частью
списочного выражения. Если их не поставить, выражение будет
вычисляться по мере надобности — когда очередной элемент становится
нужен. Заключая списочное выражение в квадратные скобки, мы тем
самым даем инструкцию сразу создать все элементы и составить из них
список. Пока что мы в основном будем пользоваться именно такими
списочными выражениями — заключенными в квадратные скобки и
превращенными таким образом в список.
Использование списочных выражений
Списочные выражения часто используются для инициализации списков.
Дело в том, что в Python не принято создавать пустые списки, чтобы
потом заполнять их значениями, если можно этого избежать.
Если все-таки необходимо создать пустой список (скажем, длиной 10) и
заполнить его нулями (не может же он быть совсем пустой), это легко
сделать, используя умножение списка на число: [0] * 10.
Использование списочных выражений в аргументах методов
split и join. Считывание значений, введенных одной строкой
Списочные выражения часто используют в аргументах методов split и
join. Например, комбинация метода split и списочного выражения
позволяют нам удобно считать числа, записанные в одну строку:
a = [int(x) for x in '976 929 289 809 7677'.split()]evil, good =
[int(x) for x in '666 777'.split()]print(evil, good, sep='\n')666777
Здесь строка (обычно она не задается прямо в выражении, а получается
из input()) разделяется на отдельные слова с помощью split. Затем
списочное выражение пропускает каждый элемент получившегося списка
через функцию int, превращая строку '976' в число 976. Можно собрать
все получившиеся значения в один список или разложить их по
отдельным переменным с помощью множественного присваивания, как во
второй строчке примера.
Рассмотрим и пример использования метода join вместе со списочным
выражением. Выведем на одной строке список квадратов натуральных
чисел от 1 до 9: 1^2=1, 2^2=4, 3^2=9... Для этого сначала с помощью
списочного выражения сформируем список строк вида ['1^2=1', '2^2=4',
'3^2=9', ...], а затем «склеим» его в одну строку методом join:
print(', '.join(str(i) + '^2=' + str(i ** 2) for i in range(1, 10)))
1^2=1, 2^2=4, 3^2=9, 4^2=16, 5^2=25, 6^2=36, 7^2=49, 8^2=64, 9^2=81
Заметьте, что в аргументе функции join стоит списочное выражение, не
заключенное в квадратные скобки (это можно сделать, но
необязательно).
Будьте внимательны! Обычно возведение в степень обозначают
«крышечкой» перед степенью, но в Python эта «крышечка» обозначает
совсем другое, а возведение в степень выполняется оператором **. В
примере «крышечка» используется только как обозначение операции
возведения в степень.
Методы списков и строк
 Как пользоваться таблицами
 Методы списков
 Методы строк
 Функции dir и help
 Форматированный вывод. f-строки
 Цепочки вызовов
 Использование методов списков. Структура данных «Стек»

Аннотация
В материалах урока приводятся таблицы с почти полным перечнем
методов списков и строк, которые можно использовать как справочный
материал. Рассматривается неявное приведение объектов к булеву типу.
Приводятся примеры цепочек вызова методов. Появление метода pop
позволяет познакомиться с понятием стека.
Этот урок отличается от прочих: большую часть его материала не нужно
запоминать, но можно использовать как справочный материал. С этой же
целью вводятся функции dir и help.

Как пользоваться таблицами


Мы уже знакомы с некоторыми функциями для работы со списками,
строками и множествами. Мы знаем также методы для работы с
элементами множеств (add, remove, discard и т. д.), метод append,
который позволяет добавлять элементы в список, метод split для
разбиения строки на список «слов» и метод join для «сшивки» списка
строк в одну. Однако мы не знаем, как делать со списками многие
другие вещи: добавлять элементы в произвольное место, удалять
элементы и т. д. Такие задачи решаются с помощью других функций и
методов.
Далее приводится перечень основных методов списков и строк, а также
функций и специальных синтаксических конструкций для работы с ними,
включая уже знакомые нам. Если при написании программы вы забудете,
как называется тот или иной метод или какие у него аргументы, смело
заглядывайте в материалы этого урока, в документацию, пользуйтесь
поиском в Интернете или описанными здесь функциями dir и help.
Важно!
Главное — усвоить основные возможности методов для стандартных типов
строки и списка, а детали (например, порядок аргументов в методе
insert или название именованного аргумента в методе split) всегда
можно посмотреть здесь или в документации.
В таблице предполагается, что a и a2 — списки, x — элемент списка, s
и s2 — строки, c — символ (строка длины 1), n — индекс элемента
списка или строки, start, stop, step — границы среза (т. е. тоже
индексы) и шаг среза, k — натуральное число.
Для методов и функций также даны примеры выражений, которые будут
истинными True и демонстрируют действие этого метода. Например,
выражения 5 in [2, 3, 5] и 'abc'.isalpha() равны True. Их можно
подставить в оператор if (и соответствующий блок будет выполнен) или
в функцию print (и тогда она выведет True).

Методы списков
Операция Описание Пример
x in a Проверка, что x содержится 5 in [2, 3, 5]
ва
x not in a Проверка, что x не 5 not in [2, 3, 6]
содержится в а
То же, что и not (x in
a)
a + a2 Конкатенация списков, то [2, 4] + [5, 3] == [2,
есть новый список, в котором 4, 5, 3]
сначала идут все элементы a,
а затем все элементы a2
a * k Список a, повторенный k раз [2, 3] * 3 == [2, 3, 2,
3, 2, 3]
a[n] n-й элемент списка, [2, 3, 7][0] == 2
отрицательные n — для [2, 3, 7][-1] == 7
отсчета с конца
a[start:stop:step] Срез списка [2, 3, 7][:2] == [2, 3]
len(a) Длина списка len([2, 3, 7]) == 3
max(a) Максимальный элемент max([2, 3, 7]) == 7
списка
min(a) Минимальный элемент min([2, 3, 7]) == 2
списка
sum(a) Сумма элементов списка sum([2, 3, 7]) == 12
a.index(x) Индекс первого вхождения x [2, 3, 7].index(7) == 2
вa
(вызовет ошибку, если x
not in a, то есть если х
отсутствует в а)
a.count(x) Количество вхождений x в a [2, 7, 3, 7].count(7)
== 2
a.append(x) Добавить x в конец a a = [2, 3, 7]
a.append(8)
a == [2, 3, 7, 8]
a.extend(a2) Добавить элементы a = [2, 3, 7]
коллекции a2 в конец a a.extend([8, 4, 5])
a == [2, 3, 7, 8, 4, 5]
del a[n] Удалить n-й элемент списка a = [2, 3, 7]
del a[1]
a == [2, 7]
del a[start:stop:step] Удалить из a все элементы, a = [2, 3, 7]
попавшие в срез del a[:2]
a == [7]
a.clear() Удалить из a все элементы a.clear()
(то же, что del a[:])
a.copy() Копия a (то же, что и полный b = a.copy()
срез a[:])
a += a2 Заменить содержимое
a *= k списка на a + a2
и a * k соответственно
a.insert(n, x) Вставить x в a на позицию n, a = [2, 3, 7]
подвинув последующую a.insert(0, 8)
часть дальше a == [8, 2, 3, 7]
a.pop(n) Получить n-й элемент списка a = [2, 3, 7]
и одновременно удалить его a.pop(1) == 3
из списка. a == [2, 7]
Вызов метода без
аргументов равносилен
удалению последнего
элемента:
a.pop() == a.pop(-1)
a.remove(x) Удалить первое вхождение x a = [2, 3, 7]
в a, в случае x not in a — a.remove(3)
ошибка a == [2, 7]
a.reverse() Изменить порядок a = [2, 3, 7]
элементов в a на обратный a.reverse()
(перевернуть список) a == [7, 3, 2]
a.sort() Отсортировать список по a = [3, 2, 7]
возрастанию a.sort()
a == [2, 3, 7]
a.sort(reverse=True) Отсортировать список по a = [3, 2, 7]
убыванию a.sort(reverse = True)
a == [7, 3, 2]
bool(a) Один из способов проверить
список на пустоту
(возвращает True, если
список непустой,
и False в противном случае)
Методы строк
Операция Описание Пример
s2 in s Проверка, что подстрока s2 'm' in 'team'
содержится в s
s2 not in s Проверка, что подстрока s2 'I' not in 'team'
не содержится в s
то же, что not (s2 in
s)
s + s2 Конкатенация (склейка) 'tea' + 'm' == 'team'
строк, то есть строка,
в которой сначала идут все
символы из s,
а затем все символы из s2
s * k Строка s, повторенная k раз 'ha' * 3 == 'hahaha'
s[n] n-й элемент строки, 'team'[2] == 'a'
отрицательные n — для 'team'[-1] == 'm'
отсчета с конца
s[start:stop:step] Срез строки 'mama'[:2] == 'ma'
len(s) Длина строки len('abracadabra') ==
11
s.find(s2) Индекс начала первого или s = 'abracadabra'
s.rfind(s2) последнего s.find('ab') == 0
вхождения подстроки s2 в s s.rfind('ab') == 7
(вернет -1, если s2 not in s.find('x') == -1
s)
s.count(s2) Количество 'abracadabra'.count('a'
неперекрывающихся ) == 5
вхождений s2 в s
s.startswith(s2) Проверка, что s начинается с 'abracadabra'.startswit
s.endswith(s2) s2 или оканчивается на s2 h('abra')
s += s2 Заменить содержимое
s *= k строки на
s + s2 и s * k
соответственно
s.isdigit() Проверка, что в строке s все '100'.isdigit()
s.isalpha() символы — цифры, 'abc'.isalpha()
s.isalnum() буквы (включая 'E315'.isalnum()
кириллические),
цифры или буквы
соответственно
s.islower() Проверка, что в строке s не 'hello!'.islower()
s.isupper() встречаются большие буквы, '123PYTHON'.isupper()
маленькие буквы.
Обратите внимание, что для
обеих этих функций знаки
препинания и цифры дают
True
s.lower() Строка s, в которой все 'Привет!'.lower() ==
s.upper() буквы (включая 'привет!'
кириллические) 'Привет!'.upper() ==
приведены к верхнему или 'ПРИВЕТ!'
нижнему регистру,
т. е. заменены на строчные
(маленькие) или заглавные
(большие)
s.capitalize() Строка s, в которой первая 'привет'.capitalize()
буква — заглавная == 'Привет'
s.lstrip() Строка s, у которой удалены ' Привет! '.strip() ==
s.rstrip() символы пустого 'Привет!'
s.strip() пространства
(пробелы, табуляции) в
начале,
в конце или с обеих сторон
s.ljust(k, c) Добавляет справа или слева 'Привет'.ljust(8, '!')
s.rjust(k, c) нужное количество == 'Привет!!'
символов c, чтобы длина s
достигла k
s.join(a) Склеивает строки из списка a '+'.join(['Вася',
через символ s 'Маша']) == 'Вася+Маша'
s.split(s2) Список всех слов строки s 'Раз два
(подстрок, разделенных три!'.split('а') ==
строками s2) ['Р', 'з дв', ' три!']
s.replace(s2, s3) Cтрока s, в которой все 'Раз два
неперекрывающиеся три!'.replace('а', 'я')
вхождения s2 заменены на =='Ряз двя три!'
s3 'Раз два
Есть необязательный три!'.replace('а', 'я',
третий параметр, с 1) == 'Ряз два три!'
помощью которого можно
указать, сколько раз
производить замену
list(s) Список символов из строки list('Привет') ==
строки s ['П', 'р', 'и', 'в',
'е', 'т']
bool(s) Проверка, что строка не
пустая (возвращает True,
если не пустая, и False в
противном случае)
int(s) Если в строке s записано int('25') == 25
float(s) целое (дробное) число,
получить это число, иначе —
ошибка
str(x) Представить любой объект x str(25) == '25'
в виде строки
Важно!
Обратите внимание: никакие методы строк, включая s.replace(...), не
изменяют саму строку s. Все они лишь возвращают измененную строку, в
отличие от большинства методов списков.
a.sort(), например, ничего не возвращает, а изменяет сам список a.

Функции dir и help


Для получения информации о списке методов любого объекта (в том
числе тех, о которых вы вряд ли хотели узнать) в Python существует
специальная функция dir. Например, dir([]) вернет все методы
списков, и оператор print(dir([])) выведет длинный список,
оканчивающийся так: 'index', 'insert', 'pop', 'remove', 'reverse',
'sort'.
Если же нам нужно узнать справочную информацию по конкретному методу
или типу данных, для этого существует функция help. help([]) выведет
на экран много информации, большая часть которой пока лишняя. А вот
help([].insert) выведет на экран краткую справку именно по методу
insert, подсказывая, что первый аргумент этого метода — индекс, а
второй — тот объект, который нужно вставить в список на этот индекс.
Важно!
Заметьте: при вызове справки по методу help([].insert) после insert
нет скобок (...) — ведь мы не хотим вызвать этот метод, чтобы
вставить что-то в какой-то список. Функции help в качестве аргумента
передается сам метод insert.

Форматированный вывод. f-строки


Этот блок урока не имеет отношения к методам списков и строк, но
позволит нам познакомиться с возможностями форматированного вывода
на экран переменных и выражений.
Начиная с версии 3.6 в Python появился новый тип строк — f-строки,
которые улучшают читаемость кода и работают быстрее других способов
форматирования.
f-строки
f-строки, которые буквально означают formatted string, задаются с
помощью литерала f перед кавычками:
>>> "обычная строка">>> f"f-строка"
f-строки делают очень простую вещь: они берут значения переменных,
которые есть в текущей области видимости, и подставляют их в строку.
В самой строке вам лишь нужно указать имя этой переменной в фигурных
скобках.
name = "Аркадий"age = 14print(f"Меня зовут {name} Мне {age}
лет.")Меня зовут Аркадий. Мне 14 лет.
В качестве подставляемого значения внутри фигурных скобок может
быть: имя переменной (f"Меня зовут {name}"), элемент списка
(f"Третий месяц в году - {month[2]}") или словаря, методы объектов
(f"Имя: {name.upper()}"). f-строки позволяют выполнять базовые
арифметические операции (f"({x} + {y}) / 2 = {(x + y) / 2}") и даже
вызывать функции (f"13 / 7 = {round(13/7)}").
Кроме того, вы можете задавать форматирование для чисел.

 Указать необходимое количество знаков после запятой,


спецификатор f отвечает за вывод чисел с плавающей точкой (тип
float):
print(f"Число пи по Архимеду - {(22/7):.2f}")

 Представить результат в двоичной системе счисления, используя


спецификатор b:
print(f"10 в двоичной системе счисления - {(10):b}")
Аналогично для шестнадцатеричной системы счисления используется
спецификатор x, а для восьмеричной — o.
Подробнее о допустимых вариантах форматирования можно почитать в
документации или на вот этом ресурсе.

Цепочки вызовов
Бывает удобно строить последовательные цепочки вызовов методов.
Например, s.strip().lower().replace('ё', 'е') выдаст строку s, в
которой убраны начальные и конечные пробелы, все буквы сделаны
маленькими, после чего убраны все точки над Ё. В результате этого
преобразования строка ' Зелёный клён ' превратится в 'зеленый клен'.
Другой пример:
'мало Средне МНОГО'.lower().split().index('средне') 1
В данном примере строка сначала полностью приводится к нижнему
регистру (все буквы маленькие) при помощи метода lower(). Затем она
превращается в список слов ['мало', 'средне', 'много'] при помощи
split(). Далее метод index находит в этом списке слово «средне» на
позиции номер 1.

Использование методов списков. Структура данных «Стек»


Приведем пример использования методов списков append и pop для
моделирования структуры данных «Стек». Эта структура данных часто
используется при решении различных задач (например, при вычислении
выражений).
Представьте себе стопку сложенных футболок или любых других
неодинаковых предметов, которые можно сложить в стопку. Из стопки
удобно забрать самый верхний предмет — тот, который положили в нее
последним. Если вы полностью разберете стопку, будете брать футболки
в порядке, обратном тому, в котором их в нее клали.
Стек
Структура данных называется стек (stack, что и значит «стопка»). По-
английски такую организацию данных называют LIFO — Last In First Out
— Первым Пришел Последним Ушел!
Если пользоваться только методами append и pop без аргументов,
список оказывается как раз такой стопкой.
Так, в примере ниже порядок вывода будет обратным порядку ввода:
stack = []for i in range(5): print('Какую футболку вы кладёте
сверху стопки?') stack.append(input())while stack: # пока стопка
не закончилась print('Сегодня вы надеваете футболку',
stack.pop())Какую футболку вы кладёте сверху стопки?белуюКакую
футболку вы кладёте сверху стопки?краснуюКакую футболку вы кладёте
сверху стопки?синююКакую футболку вы кладёте сверху стопки?
зеленуюКакую футболку вы кладёте сверху стопки?веселуюСегодня вы
надеваете футболку веселуюСегодня вы надеваете футболку
зеленуюСегодня вы надеваете футболку синююСегодня вы надеваете
футболку краснуюСегодня вы надеваете футболку белую
Здесь использовалась конструкция while stack:. В условии оператора
if или while любой объект интерпретируется как bool: либо как True,
либо как False. В случае списков и строк в False превращаются только
[] и '' соответственно (а в случае чисел — только ноль).
Иными словами, можно было бы написать while bool(stack): или while
stack != []: и получить тот же самый результат, но самый короткий и
общепринятый вариант — просто while stack:.
Вложенные списки
Аннотация
Мы уже упоминали о том, что элементами списка могут быть любые
объекты — числа, строки, кортежи, множества и даже другие списки.
Сегодня мы рассмотрим подробнее списки, элементами которых являются
другие (вложенные) списки.

Вложенные списки. Двумерные вложенные списки (матрицы)


Язык Python не ограничивает нас в уровнях вложенности: элементами
списка могут быть списки, их элементами могут быть другие списки,
элементами которых в свою очередь могут быть другие списки и т. д.
Но для решения практических задач сначала важно научиться работать с
двумерными списками.
С помощью таких списков очень удобно представить прямоугольную
таблицу (матрицу) — каждый вложенный список при этом будет являться
строкой. Именно такая структура данных используется, например, для
представления игровых полей при программировании таких игр, как
шахматы, крестики-нолики, морской бой, 2048.

Создание двумерного списка


Создание двумерного списка
Важно понять, что список списков принципиально ничем не отличается,
например, от списка чисел. Чтобы задать список списков в программе,
мы также перечисляем элементы через запятую в квадратных скобках:
table = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Если элементы списка вводятся через клавиатуру (каждая строка
таблицы на отдельной строке, всего n строк, числа в строке
разделяются пробелами), для ввода списка можно использовать
следующий код:
table = []for i in range(n): row = [int(el) for el in
input().split()] table.append(row)
В этом примере мы используем метод append, передавая ему в качестве
аргумента другой список. Так у нас получается список списков.
Списочные выражения
Для создания вложенных списков можно использовать списочные
выражения. Например, список из предыдущего примера можно создать
так:
table = [[int(el) for el in input().split()] for i in range(n)]
Попробуем теперь составить список размером 10×10 элементов,
заполненный нулями (такая задача нередко возникает при написании
различных программ). Может показаться, что сработает конструкция a =
[[0] * 10] * 10, но это не так. Попробуйте понять почему.
Подсказка: создайте такой список, измените в нем один элемент и
посмотрите, что получилось.
Самый короткий способ выполнить такую задачу — при помощи списочного
выражения:
[[0] * 10 for _ in range(10)] [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[0, 0,
0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0,
0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0,
0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0,
0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
Важно!
Обратите внимание: в этом примере используется переменная _. Это
вполне законное имя переменной, как и, например, i. Однако по
соглашению оно используется для переменной-счетчика только в том
случае, когда принимаемые этой переменной значения не важны, а важно
лишь количество итераций.
Подобное имя переменной можно было бы использовать и в первом
примере списочного выражения:
table = [[int(el) for el in input().split()] for _ in range(n)]

Перебор элементов двумерного списка. Вывод списка на экран


Для доступа к элементу списка мы должны указать индекс этого
элемента в квадратных скобках. В случае двумерных вложенных списков
мы должны указать два индекса (каждый в отдельных квадратных
скобках), в случае трехмерного списка — три индекса и т. д. В
двумерном случае сначала указывается номер строки, затем — номер
столбца (сначала выбирается вложенный список, а затем — элемент из
него).
table = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]print(table[0][0], table[0]
[1], table[1][0])
Для того чтобы перебрать все элементы матрицы (чтобы, например,
вывести их на экран), обычно используются вложенные циклы. Например,
список из предыдущего примера можно вывести на экран таким образом:
for i in range(3): for j in range(3): print(table[i][j],
end='\t') print()
В этом примере мы перебирали индексы элементов. А что будет, если
перебирать сами элементы? Например, если мы хотим подсчитать сумму
всех элементов матрицы, можно написать такой цикл:
s = 0for row in table: s += sum(row)print(s)

Матрицы
В некоторых задачах этого урока вам встретится важный математический
объект, который называется «матрица».
Матрица
Матрица — прямоугольная табличка, заполненная какими-то значениями,
обычно числами.
В математике вам встретится множество различных применений матриц,
поскольку с их помощью многие задачи гораздо проще сформулировать и
решить. Мы же сконцентрируемся на том, как хранить матрицу в памяти
компьютера.
В первую очередь от матрицы нам нужно уметь получать элемент в i-й
строке и j-м столбце. Чтобы этого добиться, обычно поступают так:
заводят список строк матрицы, а каждая строка матрицы сама по себе
тоже является списком элементов. То есть мы получили список списков
чисел. Теперь, чтобы получить элемент, нам достаточно из списка
строк матрицы выбрать i-ю и из этой строки взять j-й элемент.
Давайте заведем простую матрицу M размера 2×3 (2 строки и 3 столбца)
и получим элемент на позиции (1, 3). Обратите внимание: в математике
нумерация строк и столбцов идет с единицы, а не с нуля. И, по
договоренности среди математиков, сначала всегда указывается строка,
а лишь затем — столбец. Элемент на i-ой строке, j-м столбце матрицы
M в математике обозначается Mi,j. Итак:
matrix = [[1, 2, 3], [2, 4, 6]]print(matrix[0][2]) # =>
3
matrix — вся матрица, matrix[0] — список значений в первой строке,
matrix[0][2] — элемент в третьем столбце в этой строке.
Чтобы перебрать элементы матрицы, приходится использовать двойные
циклы. Например, выведем на экран все элементы матрицы, перебирая их
по столбцам:
for col in range(3): for row in range(2):
print(matrix[row][col])
Знакомство со словарями
Аннотация
В этом уроке рассказывается о словарях — встроенной в Python мощной
структуре данных. В других языках аналогичная структура называется
map, HashMap, Dictionary.
Базовые функции работы со словарями показаны на простых примерах
хранения библиотеки знаний о фильмах и актерах.

Знакомство со словарями
Списки — удобный и самый популярный способ сохранить большое
количество данных в одной переменной. Списки индексируют все
хранящиеся в них элементы. Первый элемент, как мы помним, лежит по
индексу 0, второй — по индексу 1 и т. д. Такой способ хранения
позволяет быстро обращаться к элементу списка, зная его индекс.
actors = ['Джонни Депп', 'Эмма Уотсон', 'Билли
Пайпер']print(actors[1])
Представим, что мы делаем свою онлайн-энциклопедию об актерах
мирового кино (наподобие Википедии). Для каждого актера нужно
сохранить текст статьи о нем. Ее название — строка, состоящая из
фамилии и имени актера. Как правильно хранить такие данные?
Можно создать список кортежей. Каждый кортеж будет состоять из двух
строк — названия и текста статьи.
actors = [('Джонни Депп', 'Джон Кристофер Депп Второй родился '
'9 июня 1963 года в Овенсборо, Кентукки...'), ('Сильвестр Сталлоне',
'Сильвестр Гарденцио Сталлоне родился в Нью-Йорке. '
'Его отец, парикмахер Фрэнк Сталлоне — иммигрант из Сицилии...'),
('Эмма Уотсон', 'Эмма Шарлотта Дуерр Уотсон родилась в семье
английских адвокатов. ' 'В пять лет переехала вместе
с семьей из Парижа в Англию...'), # ... ]
Со временем количество статей значительно вырастет. Чтобы найти
нужную статью по названию, нам придется написать цикл for, который
пройдет по всем элементам списка actors и найдет в нем кортеж,
первый элемент которого равен искомому названию. В приведенном выше
примере, чтобы найти статью об Эмме Уотсон, нам придется в цикле
пройти мимо Джонни Деппа и Сильвестра Сталлоне. Угадать заранее, что
статья об Эмме Уотсон лежит после них, не получится.
Корень этой проблемы в том, что списки индексируются целыми числами.
Мы же хотим находить информацию не по числу, а по строке — названию
статьи. Было бы здорово, если бы индексами могли быть не числа, а
строки. В списках это невозможно, однако возможно в словарях!
Словарь
Словарь (в Python он называется dict) — тип данных, позволяющий, как
и список, хранить много данных. В отличие от списка, в словаре для
каждого элемента можно самому определить «индекс», по которому он
будет доступен. Этот индекс называется ключом.

Создание словаря
Вот пример создания словаря для энциклопедии об актерах мирового
кино:
actors = { 'Джонни Депп': 'Джон Кристофер Депп Второй родился 9 июня
1963 года ' 'в Овенсборо, Кентукки...', 'Сильвестр
Сталлоне': 'Сильвестр Гарденцио Сталлоне родился в Нью-Йорке. '
'Его отец, парикмахер Фрэнк Сталлоне — иммигрант из Сицилии...',
'Эмма Уотсон': 'Эмма Шарлотта Дуерр Уотсон родилась в семье
английских адвокатов. ' 'В пять лет переехала вместе
с семьей из Парижа в Англию...', # ... }
Создание словаря
Элементы словаря перечисляются в фигурных скобках (как и элементы
множества!) и разделяются запятой. До двоеточия указывается ключ, а
после двоеточия — значение, доступное в словаре по этому ключу.
Пустой словарь можно создать двумя способами:
d = dict()# или такd = {}
Вспомните, что создать пустое множество можно, только используя
функцию set(). Теперь понятно, почему это так — пустые фигурные
скобки зарезервированы для создания словаря.

Обращение к элементу словаря


После инициализации словаря мы можем быстро получать статью про
конкретного актера:
print(actors['Эмма Уотсон'])
Важно!
Обращение к элементу словаря выглядит как обращение к элементу
списка, только вместо целочисленного индекса используется ключ. В
качестве ключа можно указать выражение: Python вычислит его
значение, прежде чем обратится к искомому элементу.
first_name = 'Сильвестр'last_name =
'Сталлоне'print(actors[first_name + ' ' + last_name])
Если ключа в словаре нет, возникнет ошибка:
print(actors['Несуществующий ключ'])KeyError: 'Несуществующий ключ'

Добавление и удаление элементов


Важная особенность словаря — его динамичность. Мы можем добавлять
новые элементы, изменять их или удалять. Изменяются элементы точно
так же, как в списках, только вместо целочисленного индекса в
квадратных скобках указывается ключ:
actors['Эмма Уотсон'] = 'Новый текст статьи об Эмме Уотсон'
Также в словари можно добавлять новые элементы и удалять
существующие.
Добавление элемента
Добавление синтаксически выглядит так же, как и изменение:
actors['Брэд Питт'] = 'Уильям Брэдли Питт, более известный как Брэд
Питт — ' \ 'американский актёр и продюсер. ' \
'Лауреат премии «Золотой глобус» за 1995 год, ...'
Удаление элемента
Для удаления можно использовать инструкцию del (как и в списках):
del actors['Джонни Депп']# больше в словаре нет ни ключа 'Джонни
Депп', # ни соответствующего ему значенияprint(actors['Джонни
Депп'])KeyError: 'Джонни Депп'
Удаление элемента
Удалять элемент можно и по-другому:
actors.pop('Джонни Депп')
Единственное отличие этого способа от вызова del — он возвращает
удаленное значение. Можно написать так:
deleted_value = actors.pop('Джонни Депп')
В переменную deleted_value положится значение, которое хранилось в
словаре по ключу 'Джонни Депп'. В остальном этот способ идентичен
оператору del. В частности, если ключа 'Джонни Депп' в словаре нет,
возникнет ошибка KeyError.
Важно!
Чтобы ошибка не появлялась, этому методу можно передать второй
аргумент. Он будет возвращен, если указанного ключа в словаре нет.
Это позволяет реализовать безопасное удаление элемента из словаря:
deleted_value = actors.pop('Джонни Депп', None)
Если ключа 'Джонни Депп' в словаре нет, в deleted_value попадет
None.

Проверка наличия элемента в словаре


Оператор in позволяет проверить, есть ли ключ в словаре:
if 'Джонни Депп' in actors: print('У нас есть статья про Джонни
Деппа')
Проверить, что ключа нет, можно с помощью аналогичного оператора not
in:
if 'Сергей Безруков' not in actors: print('У нас нет статьи о
Сергее Безрукове')

Нестроковые ключи
Решим следующую задачу. Пусть дан длинный список целых чисел
numbers. Мы знаем, что некоторые числа встречаются в этом списке
несколько раз. Нужно узнать, сколько именно раз встречается каждое
из чисел.
numbers = [1, 10, 1, 6, 4, 10, 4, 2, 2, 1, 10, 1]counts = {}for
number in numbers: if number not in counts: counts[number]
= 1 else: counts[number] += 1
Просто так сделать counts[number] += 1 нельзя: если ключа number в
словаре нет, возникнет ошибка KeyError.
В результате работы этой программы все элементы из списка numbers
окажутся ключами словаря counts. Значением counts[x] будет
количество раз, которое число x встретилось в списке numbers. Как
это работает?
Цикл for перебирает все элементы списка numbers и для каждого
проверяет, присутствует ли он уже в качестве ключа в counts. Если
нет — значит, число встретилось нам впервые и мы инициализируем
значение counts[numbers] = 1. Иначе увеличим counts[number] на
единицу, поскольку число number встретилось нам повторно.
Почему для этой задачи не стоит использовать список, хотя ключи —
обычные целые числа? Потому что, используя словарь, мы можем решить
эту задачу и для вещественных чисел, и для очень больших целых
чисел, и вообще для любых объектов, которые можно сравнивать.

Методы словарей
Взять значение в словаре можно не только с помощью квадратных
скобок, но и с помощью метода get:
article = actors.get('Джонни Депп')
Преимущество метода в том, что, кроме ключа, он может принимать и
второй аргумент — значение, которое вернется, если заданного ключа
нет:
article = actors.get('Джонни Депп', 'Статья о Джонни Деппа не
найдена')
Воспользуемся этим приемом для улучшения нашей программы в задаче о
повторяющихся числах:
numbers = [1, 10, 1, 6, 4, 10, 4, 2, 2, 1, 10, 1]counts = {}for
number in numbers: counts[number] = counts.get(number, 0) + 1
Попробуйте понять, почему это работает верно.
Все ключи словаря можно перебрать циклом for:
for actor_name in actors: print(actor_name, actors[actor_name])
Другой способ сделать то же самое — вызвать метод .keys():
for actor_name in actors.keys(): print(actor_name,
actors[actor_name])
Метод .keys()
С помощью метода .keys() можно получить список всех ключей словаря:
actors_names = list(actors.keys())
Метод .values()
Есть и парный метод .values(), возвращающий все значения словаря:
all_articles = list(actors.values())
Он позволяет, например, проверить, есть ли какое-нибудь значение
value среди значений словаря:
value in d.values()
Метод .items()
Если вы хотите перебрать элементы словаря d так, чтобы в переменной
key оказывался ключ, а в value — соответствующее ему значение, это
можно сделать с помощью метода .items() и цикла for.
for key, val in d.items():
Например:
for actor_name, article in actors.items(): print(actor_name,
article)
Допустимые типы ключей
Мы уже выяснили, что ключами в словарях могут быть строки и целые
числа. Кроме этого, ключами могут быть вещественные числа и кортежи.
Ключи в словаре
Ключами в словаре не могут быть другие словари. В принципе в одном
словаре могут быть ключи разных типов, однако обычно принято
использовать однотипные ключи.
Вообще, есть строгий способ определить, может ли объект быть ключом
в словаре. Для этого объект должен быть неизменяемым. Неизменяемые
объекты не могут поменять значение в себе во время выполнения
программы. Неизменяемыми в Python являются числа, строки и кортежи.
Именно их обычно и используют в качестве ключей словарей.
Вот как может выглядеть словарь с ключами-кортежами. В качестве
ключа используются координаты, а в качестве значения — название
города.
cities = { (55.75, 37.5): 'Москва', (59.8, 30.3): 'Санкт-
Петербург', (54.32, 48.39): 'Ульяновск'}print(cities[(55.75,
37.5)])cities[(53.2, 50.15)] = 'Самара'
Возможно, нам захочется развернуть этот словарь, то есть построить
такой, в котором ключами будут города, а значениями — их координаты.
coordinates = {}for coordinate, city in cities.items():
coordinates[city] = coordinate
Если в исходном словаре были повторяющиеся значения, некоторые из
них потеряются при разворачивании словаря. Это объясняется тем, что
значения в словаре могут повторяться, а вот ключи обязаны быть
уникальными.
Значениями в словаре, в отличие от ключей, могут быть объекты любого
типа — числа, строки, кортежи, списки и даже другие словари. Вот,
например, как можно сохранить список фильмов для каждого из актеров:
films = { 'Джонни Депп': [ 'Эдвард Руки-Ножницы',
'Одинокий рейнджер', 'Чарли и шоколадная фабрика', ..],
'Эмма Уотсон': [ 'Гарри Поттер и философский камень',
'Красавица и Чудовище', ..], # ...}# Вывести список фильмов,
в которых снималась Эмма Уотсонprint(films['Эмма Уотсон'])#
Проверить, снимался ли Джонни Депп в фильме «Чарли и шоколадная
фабрика»if 'Чарли и шоколадная фабрика' in films['Джонни Депп']:
print('Снимался!')

Вам также может понравиться