Открыть Электронные книги
Категории
Открыть Аудиокниги
Категории
Открыть Журналы
Категории
Открыть Документы
Категории
Аннотация
Первый урок посвящен введению в язык Python и знакомству с теми техническими
средствами, которые понадобятся нам для обучения.
Сегодня мы научимся писать программы, которые умеют что-то выводить на
экран и считывать информацию с клавиатуры. И познакомимся с переменными.
Введение
Программа — список команд, то есть инструкций для компьютера:
Знакомство с IDE
Команды для интерпретатора можно писать в обычном текстовом редакторе
(например, в «Блокноте»). Но чаще для этого пользуются специальной программой,
которая называется средой разработки (англ. IDE, Integrated Development
Environment). Среда разработки — тоже текстовый редактор, но с дополнительными
возможностями. Например, она умеет сама находить на компьютере программу-
интерпретатор и запускать одной кнопкой. Среда разработки, кроме того, форматирует
написанный вами код, чтобы его удобно было читать, а иногда даже подсказывает, где
вы допустили ошибку.
На первом этапе мы будем использовать среду разработки Wing IDE. Ее можно скачать
с сайта разработчика, фирмы Wingware. В будущем вам может потребоваться более
сложная и более богатая возможностями среда разработки. В этом случае мы
рекомендуем использовать PyCharm — продукт российской фирмы JetBrains.
Ну что же, пора приступать к разработке программ. Для начала запустите среду
разработки WingIDE. Давайте проверим настройки кодировок файлов. Эти настройки
потребуются для корректной сдачи программ в тестирующую систему.
Настало время запустить первую программу. Однако кнопка запуска 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 будет игнорировать
всю эту строчку. Программа будет выполняться так, как будто строчки нет. Такая
строчка называется комментарием.
Комментарии нужны в двух случаях:
Повторение
На прошлом уроке мы познакомились с переменными. Переменная имеет имя и
значение. Имя переменной может начинаться только с буквы и включать в себя буквы,
цифры и символ подчеркивания. Имя переменной должно отражать ее назначение.
Чтобы задать переменной значение, необходимо после знака равно (оператора
присваивания) указать значение переменной.
Еще значение переменной можно получить из ввода. Для этого используем команду
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=="Тук-тук":
Объекты любой однородной группы можно сравнивать между собой. Подумайте над
тем, как можно сравнивать, например, строки.
PEP 8
По стандарту PEP 8 длина строки должна быть ограничена максимум 79 символами.
Есть несколько способов переноса длинных строк.
Вложенные условия
Блок кода
В команде 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('Засим - заканчиваем.')
А более простой вариант этой программы теперь попробуйте написать
самостоятельно.
Команда 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 // 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:
Простейшие функции
С действиями над числами определились, осталось разобраться, как получать числа из
ввода. Здесь нам поможет важное новое понятие — функция. В математике функция
из одного числа (или даже нескольких) делает другое.
Функция
В программировании (и в 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
Каждый раз, когда вы пишете программу, важно понимать, какой тип имеет каждое
значение и каждая переменная.
Цикл 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 — ложно.
Поэтому цикл завершается, тело цикла больше не выполняется, прыгаем
сразу на следующую после цикла строчку программы — шестую. Она
выводит последнее сообщение.
Все.
Сигнал остановки
Рассмотрим такую задачу: пользователь вводит числа. Пусть это будут
цены на купленные в магазине товары, а наша программа — часть
программного обеспечения кассового аппарата. Ввод −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)
Типы ошибок
Вероятно, вы уже обратили внимание, что при написании программ у вас
возникали хоть и разные ошибки, но у многих из них было что-то
общее. На самом деле существуют три основных типа ошибок, которые
нужно научиться различать, так вы сможете без труда их исправить.
Синтаксическая ошибка: происходит, когда встречается код, который не
соответствует правилам языка 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 и выведены иконками (после
кнопки запуска) в панели меню. Еще их можно запускать горячими
клавишами.
Точка остановки
А теперь при помощи отладчика поищем ошибки в другой программе.
Рассмотрим вот такую программу под названием 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.
Цикл 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...), хотя
нигде нет оператора присваивания = или его родственников типа +=.
Сравнение множеств
Все операторы сравнения множеств, а именно: ==, <, >, <=, >=,
возвращают 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, но целиком не совпадает с ним».
Строки. Индексация
Аннотация
На этом занятии мы углубим свои знания о строках. Теперь мы сможем
не только считывать строку, но и работать с ней, в том числе делать
посимвольный перебор.
Индексация в строках
В отличие от множеств, в строках важен порядок элементов (символов).
Действительно, если множества {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] — предпоследний и т д.
Срезы строк
На примере разобранной задачи мы увидели, что перебор элементов
строки с помощью конструкции 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
Срезы списков
Как и для строк, для списков определена операция взятия среза:
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)
Списочные выражения
Списочные выражения
Для генерации списков из неповторяющихся элементов в 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 и списочным выражением:
Аннотация
В материалах урока приводятся таблицы с почти полным перечнем
методов списков и строк, которые можно использовать как справочный
материал. Рассматривается неявное приведение объектов к булеву типу.
Приводятся примеры цепочек вызова методов. Появление метода pop
позволяет познакомиться с понятием стека.
Этот урок отличается от прочих: большую часть его материала не нужно
запоминать, но можно использовать как справочный материал. С этой же
целью вводятся функции dir и help.
Методы списков
Операция Описание Пример
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.
Цепочки вызовов
Бывает удобно строить последовательные цепочки вызовов методов.
Например, s.strip().lower().replace('ё', 'е') выдаст строку s, в
которой убраны начальные и конечные пробелы, все буквы сделаны
маленькими, после чего убраны все точки над Ё. В результате этого
преобразования строка ' Зелёный клён ' превратится в 'зеленый клен'.
Другой пример:
'мало Средне МНОГО'.lower().split().index('средне') 1
В данном примере строка сначала полностью приводится к нижнему
регистру (все буквы маленькие) при помощи метода lower(). Затем она
превращается в список слов ['мало', 'средне', 'много'] при помощи
split(). Далее метод index находит в этом списке слово «средне» на
позиции номер 1.
Матрицы
В некоторых задачах этого урока вам встретится важный математический
объект, который называется «матрица».
Матрица
Матрица — прямоугольная табличка, заполненная какими-то значениями,
обычно числами.
В математике вам встретится множество различных применений матриц,
поскольку с их помощью многие задачи гораздо проще сформулировать и
решить. Мы же сконцентрируемся на том, как хранить матрицу в памяти
компьютера.
В первую очередь от матрицы нам нужно уметь получать элемент в 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(). Теперь понятно, почему это так — пустые фигурные
скобки зарезервированы для создания словаря.
Нестроковые ключи
Решим следующую задачу. Пусть дан длинный список целых чисел
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('Снимался!')