Изучаем Python Эрик Метиз. Crash course2 n d e d i t i o na h a n d s o n, p r o j e c t b a s e d i n t r o d u c t i o n t o p r o g r a m m i n g
Скачать 6.19 Mb.
|
magicians.py ❶ magicians = ['alice', 'david', 'carolina'] ❷ for magician in magicians: ❸ print(magician) Все начинается с определения списка , как и в главе 3. В точке определяется цикл for . Эта строка приказывает Python взять очередное имя из списка и сохра- нить его в переменной magician . В точке выводится имя, только что сохранен- Перебор всего списка 65 ное в переменной magician . Затем строки и повторяются для каждого имени в списке. Этот код можно описать так: «Для каждого фокусника в списке вывести его имя». Результат представляет собой простой перечень имен из списка: alice david carolina Подробнее о циклах Концепция циклов очень важна, потому что она представляет один из основных способов автоматизации повторяющихся задач компьютером. Например, в простом цикле, использованном в magicians .py , Python сначала читает первую строку цикла: for magician in magicians: Эта строка означает, что нужно взять первое значение из списка magicians и со- хранить его в переменной magician . Первое значение в списке — 'alice' . Затем Python читает следующую строку: print(magician) Python выводит текущее значение magician , которое все еще равно 'alice' . Так как в списке еще остались другие значения, Python возвращается к первой строке цикла: for magician in magicians: Python берет следующее значение из списка, 'david' , и сохраняет его в magician Затем выполняется строка: print(magician) Python снова выводит текущее значение magician ; теперь это строка 'david' . Весь цикл повторяется еще раз с последним значением в списке, 'carolina' . Так как других значений в списке не осталось, Python переходит к следующей строке в про- грамме. В данном случае после цикла for ничего нет, поэтому программа просто завершается. Помните, что все действия повторяются по одному разу для каждого элемента в списке независимо от их количества. Если список содержит миллион элементов, Python повторит эти действия миллион раз — обычно это происходит очень быстро. Также помните, что при написании собственных циклов for временной переменной для текущего значения из списка можно присвоить любое имя. Однако на практи- ке рекомендуется выбирать осмысленное имя, описывающее отдельный элемент списка. Несколько примеров: for cat in cats: for dog in dogs: for item in list_of_items: 66 Глава 4 • Работа со списками Выполнение этого правила поможет вам проследить за тем, какие действия вы- полняются с каждым элементом в цикле for . В зависимости от того, какое число используется — одиночное или множественное, вы сможете понять, работает ли данная часть кода с отдельным элементом из списка или со всем списком. Более сложные действия в циклах for В цикле for с каждым элементом списка может выполняться практически любое действие. Дополним предыдущий пример, чтобы программа выводила для каждого фокусника отдельное сообщение: magicians.py magicians = ['alice', 'david', 'carolina'] for magician in magicians: ❶ print(f"{magician.title()}, that was a great trick!") Единственное отличие этого кода от предыдущего заключается в том, что в точке для каждого фокусника строится сообщение с его именем. При первом проходе цикла переменная magician содержит значение 'alice' , поэтому Python начинает первое сообщение с имени 'Alice' . При втором проходе сообщение будет начи- наться с имени 'David' , а при третьем — с имени 'Carolina' : Alice, that was a great trick! David, that was a great trick! Carolina, that was a great trick! Тело цикла for может содержать сколько угодно строк кода. Каждая строка с на- чальным отступом после строки for magician in magicians считается находящейся в цикле и выполняется по одному разу для каждого значения в списке. Таким об- разом, с каждым значением в списке можно выполнить любые операции на ваше усмотрение. Включим в сообщение для каждого фокусника вторую строку: magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(f"{magician.title()}, that was a great trick!") ❶ print(f"I can't wait to see your next trick, {magician.title()}.\n") Так как оба вызова print() снабжены отступами, каждая строка будет выполнена по одному разу для каждого фокусника в списке. Символ новой строки ( "\n" ) во второй команде print вставляет пустую строку после каждого прохода цикла. В результате будет создан набор сообщений, аккуратно сгруппированных для каждого фокусника в списке: Alice, that was a great trick! I can't wait to see your next trick, Alice. David, that was a great trick! I can't wait to see your next trick, David. Предотвращение ошибок с отступами 67 Carolina, that was a great trick! I can't wait to see your next trick, Carolina. Тело цикла for может содержать сколько угодно строк кода. На практике часто требуется выполнить в цикле for несколько разных операций для каждого эле- мента списка. Выполнение действий после цикла for Что происходит после завершения цикла for ? Обычно программа выводит некую сводную информацию или переходит к другим операциям. Каждая строка кода после цикла for , не имеющая отступа, выполняется без по- вторения. Допустим, вы хотите вывести сообщение для всей группы фокусников и поблагодарить их за превосходное представление. Чтобы вывести общее сообще- ние после всех отдельных сообщений, разместите его после цикла for без отступа: magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(f"{magician.title()}, that was a great trick!") print(f"I can't wait to see your next trick, {magician.title()}.\n") ❶ print("Thank you, everyone. That was a great magic show!") Первые две команды print повторяются по одному разу для каждого фокусника в списке, как было показано ранее. Но поскольку строка отступа не имеет, это сообщение выводится только один раз: Alice, that was a great trick! I can't wait to see your next trick, Alice. David, that was a great trick! I can't wait to see your next trick, David. Carolina, that was a great trick! I can't wait to see your next trick, Carolina. Thank you, everyone. That was a great magic show! При обработке данных в циклах for завершающее сообщение позволяет подвести итог операции, выполненной со всем набором данных. Например, цикл for может инициализировать игру, перебирая список персонажей и изображая каждого пер- сонажа на экране. После цикла выполняется блок без отступа, который выводит кнопку Начать игру , после того как все персонажи появятся на экране. Предотвращение ошибок с отступами В Python связь одной строки кода с предшествующей строкой обозначается от- ступами. В приведенных примерах строки, выводившие сообщения для отдельных фокусников, были частью цикла, потому что они были снабжены отступами. При- менение отступов в Python сильно упрощает чтение кода. Фактически отступы 68 Глава 4 • Работа со списками заставляют разработчика писать аккуратно отформатированный код с четкой визуальной структурой. В более длинных программах Python могут встречаться блоки кода с отступами нескольких разных уровней. Эти уровни способствуют пониманию общей структуры программы. Когда разработчики только начинают писать код, работа которого зависит от пра- вильности отступов, в их коде нередко встречаются распространенные ошибки. На- пример, иногда они расставляют отступы в коде, в котором эти отступы не нужны, или наоборот — забывают ставить отступы в блоках, в которых это необходимо. Несколько примеров помогут вам избежать подобных ошибок в будущем и успеш- но исправлять их, когда они встретятся в ваших программах. Итак, рассмотрим несколько типичных ошибок при использовании отступов. Пропущенный отступ Строка после команды for в цикле всегда должна снабжаться отступом. Если вы забудете поставить отступ, Python напомнит вам об этом: magicians.py magicians = ['alice', 'david', 'carolina'] for magician in magicians: ❶ print(magician) Команда print в точке должна иметь отступ, но здесь его нет. Когда Python ожи- дает увидеть блок с отступом, но не находит его, появляется сообщение с указанием номера строки: File "magicians.py", line 3 print(magician) ^ IndentationError: expected an indented block Обычно для устранения подобных ошибок достаточно поставить отступ в строке (или строках), следующей непосредственно после команды for Пропущенные отступы в других строках Иногда цикл выполняется без ошибок, но не выдает ожидаемых результатов. Такое часто происходит, когда вы пытаетесь выполнить несколько операций в цикле, но забываете снабдить отступом некоторые из строк. Например, вот что происходит, если вы забудете снабдить отступом вторую строку в цикле: magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!") ❶ print(f"I can't wait to see your next trick, {magician.title()}.\n") Предотвращение ошибок с отступами 69 Команда print в точке должна быть снабжена отступом, но поскольку Python находит хотя бы одну строку с отступом после команды for , сообщение об ошибке не выдается. В результате первая команда print будет выполнена для каждого элемента в списке, потому что в ней есть отступ. Вторая команда print отступа не имеет, поэтому она будет выполнена только один раз после завершения цикла. Так как последним значением magician является строка 'carolina' , второе сообщение будет выведено только с этим именем: Alice, that was a great trick! David, that was a great trick! Carolina, that was a great trick! I can't wait to see your next trick, Carolina. Это пример логической ошибки. Код имеет действительный синтаксис, но он не приводит к желаемому результату, потому что проблема кроется в его логике. Если некоторое действие должно повторяться для каждого элемента в списке, но выполняется только один раз, проверьте, не нужно ли добавить отступы в строке или нескольких строках кода. Лишние отступы Если вы случайно поставите отступ в строке, в которой он не нужен, Python со- общит об этом: hello_world.py message = "Hello Python world!" ❶ print(message) Отступ команды print в точке не нужен, потому что эта строка не подчинена предшествующей; Python сообщает об ошибке: File "hello_world.py", line 2 print(message) ^ IndentationError: unexpected indent Чтобы избежать непредвиденных ошибок с отступами, используйте их только там, где для этого существуют конкретные причины. В тех программах, которые вы пи- шете на этой стадии изучения Python, отступы нужны только в строках действий, повторяемых для каждого элемента в цикле for Лишние отступы после цикла Если вы случайно снабдите отступом код, который должен выполняться после за- вершения цикла, то этот код будет выполнен для каждого элемента. Иногда Python выводит сообщение об ошибке, но часто дело ограничивается простой логической ошибкой. 70 Глава 4 • Работа со списками Например, что произойдет, если случайно снабдить отступом строку с выводом завершающего приветствия для группы фокусников? magicians.py magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(f"{magician.title()}, that was a great trick!") print(f"I can't wait to see your next trick, {magician.title()}.\n") ❶ print("Thank you everyone, that was a great magic show!") Так как строка имеет отступ, сообщение будет продублировано для каждого фокусника в списке: Alice, that was a great trick! I can't wait to see your next trick, Alice. Thank you everyone, that was a great magic show! David, that was a great trick! I can't wait to see your next trick, David. Thank you everyone, that was a great magic show! Carolina, that was a great trick! I can't wait to see your next trick, Carolina. Thank you everyone, that was a great magic show! Это еще один пример логической ошибки наподобие описанной в разделе «Про- пущенные отступы в других строках». Python не знает, что вы пытаетесь сде- лать в своем коде, поэтому он просто выполняет весь код, не нарушающий правил синтаксиса. Если действие, которое должно выполняться один раз, вы- полняется многократно, проверьте, нет ли лишнего отступа в соответствующей строке кода. Пропущенное двоеточие Двоеточие в конце команды for сообщает Python, что следующая строка является началом цикла. magicians = ['alice', 'david', 'carolina'] ❶ for magician in magicians print(magician) Если вы случайно забудете поставить двоеточие, как в примере , произойдет синтаксическая ошибка, так как полученная команда нарушает правила языка. И хотя такие ошибки легко исправляются, найти их бывает достаточно трудно. Вы не поверите, сколько времени тратят программисты на поиск подобных «одно- символьных» ошибок. Поиск таких ошибок усложняется еще и тем, что человек обычно склонен видеть то, что он ожидает увидеть. Создание числовых списков 71 УПРАЖНЕНИЯ 4.1. Пицца: вспомните по крайней мере три названия ваших любимых видов пиццы. Со- храните их в списке и используйте цикл for для вывода всех названий. • Измените цикл for так, чтобы вместо простого названия пиццы выводилось сообще- ние, включающее это название. Таким образом, для каждого элемента должна выво- диться строка с простым текстом, например: «I like pepperoni pizza». • Добавьте в конец программы (после цикла for) строку с завершающим сообщением. Таким образом, вывод должен состоять из трех (и более) строк с названиями пиццы и дополнительного сообщения — скажем, «I really love pizza!». 4.2. Животные: создайте список из трех (и более) животных, обладающих общей характе- ристикой. Используйте цикл for для вывода названий всех животных. • Измените программу так, чтобы вместо простого названия выводилось сообщение, включающее это название, — например, «A dog would make a great pet». • Добавьте в конец программы строку с описанием общего свойства. Например, мож- но вывести сообщение «Any of these animals would make a great pet!». Создание числовых списков Необходимость хранения наборов чисел возникает в программах по многим при- чинам. Например, в компьютерной игре могут храниться координаты каждого персонажа на экране, таблицы рекордов и т. д. В программах визуализации данных пользователь почти всегда работает с наборами чисел: температурой, расстоянием, численностью населения, широтой/долготой и другими числовыми данными. Списки идеально подходят для хранения наборов чисел, а Python предоставляет специальные средства для эффективной работы с числовыми списками. Достаточно один раз понять, как эффективно пользоваться этими средствами, и ваш код будет хорошо работать даже в том случае, если список содержит миллионы элементов. Функция range() Функция range() упрощает построение числовых последовательностей. Например, с ее помощью можно легко вывести серию чисел: first_numbers.py for value in range(1,5): print(value) И хотя на первый взгляд может показаться, что он должен вывести числа от 1 до 5, на самом деле число 5 не выводится: 1 2 3 4 72 Глава 4 • Работа со списками В этом примере range() выводит только числа от 1 до 4. Перед вами еще один при- мер явления «смещения на 1», часто встречающегося в языках программирования. При выполнении функции range() Python начинает отсчет от первого переданного значения и прекращает его при достижении второго. Так как на втором значении происходит остановка, конец интервала (5 в данном случае) не встречается в вы- воде. Чтобы вывести числа от 1 до 5, используйте вызов range(1,6) : for value in range(1,6): print(value) На этот раз вывод начинается с 1 и завершается 5: 1 2 3 4 5 Если ваша программа при использовании range() выводит не тот результат, на который вы рассчитывали, попробуйте увеличить конечное значение на 1. При вызове range() также можно передать только один аргумент; в этом случае последовательность чисел будет начинаться с 0. Например, range(6) вернет числа от 0 до 5. Использование range() для создания числового списка Если вы хотите создать числовой список, преобразуйте результаты range() в список при помощи функции list() . Если заключить вызов range() в list() , то результат будет представлять собой список с числовыми элементами. В примере из предыдущего раздела числовая последовательность просто выводи- лась на экран. Тот же набор чисел можно преобразовать в список вызовом list() : numbers = list(range(1,6)) print(numbers) Результат: [1, 2, 3, 4, 5] Функция range() также может генерировать числовые последовательности, про- пуская числа в заданном диапазоне. Например, построение списка четных чисел от 1 до 10 происходит так: even_numbers.py even_numbers = list(range(2,11,2)) print(even_numbers) Создание числовых списков 73 В этом примере функция range() начинает со значения 2, а затем увеличива- ет его на 2. Приращение 2 последовательно применяется до тех пор, пока не будет достигнуто или пройдено конечное значение 11, после чего выводится результат: [2, 4, 6, 8, 10] С помощью функции range() можно создать практически любой диапазон чисел. Например, как бы вы создали список квадратов всех целых чисел от 1 до 10? В язы- ке Python операция возведения в степень обозначается двумя звездочками ( ** ). Один из возможных вариантов выглядит так: squares.py ❶ squares = [] ❷ for value in range(1,11): ❸ square = value**2 ❹ squares.append(square) ❺ print(squares) Сначала в точке создается пустой список с именем squares . В точке вы при- казываете Python перебрать все значения от 1 до 10 при помощи функции range() В цикле текущее значение возводится во вторую степень, а результат сохраняется в переменной square в точке . В точке каждое новое значение square присо- единяется к списку squares . Наконец, после завершения цикла список квадратов выводится в точке : [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] Чтобы сделать код более компактным, можно опустить временную переменную square и присоединять каждое новое значение прямо к списку: squares = [] for value in range(1,11): ❶ squares.append(value**2) print(squares) Конструкция выполняет ту же работу, что и строки и в squares .py . Каждое значение в цикле возводится во вторую степень, а затем немедленно присоединя- ется к списку квадратов. При создании более сложных списков можно использовать любой из двух под- ходов. Иногда использование временной переменной упрощает чтение кода; в других случаях оно приводит лишь к напрасному удлинению кода. Сначала сосредоточьтесь на написании четкого и понятного кода, который делает именно то, что нужно, и только потом переходите к анализу кода и поиску более эффек- тивных решений. |