Книга Изучаем Python
Скачать 4.68 Mb.
|
63 в списке. Этот код можно описать так: «Для каждого фокусника в списке вывести его имя». Результат представляет собой простой перечень имен из списка: 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: Выполнение этого правила поможет вам проследить за тем, какие действия выпол- няются с каждым элементом в цикле for . В зависимости от того, какое число ис- 64 Глава 4 • Работа со списками пользуется — одиночное и множественное, вы сможете понять, работает ли данная часть кода с отдельным элементом из списка или со всем списком. Более сложные действия в циклах for В цикле for с каждым элементом списка может выполняться практически любое действие. Дополним предыдущий пример, чтобы программа выводила для каждого фокусника отдельное сообщение: magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(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(magician.title() + ", that was a great trick!") print("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. Carolina, that was a great trick! I can't wait to see your next trick, Carolina. Перебор всего списка 65 Тело цикла for может содержать сколько угодно строк кода. На практике часто требуется выполнить в цикле for несколько разных операций для каждого эле- мента списка. Выполнение действий после цикла for Что происходит после завершения цикла for ? Обычно программа выводит сводную информацию или переходит к другим операциям. Каждая строка кода после цикла for , не имеющая отступа, выполняется без по- вторения. Допустим, вы хотите вывести сообщение для всей группы фокусников и поблагодарить их за превосходное представление. Чтобы вывести общее сообще- ние после всех отдельных сообщений, разместите его после цикла for без отступа: magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!") print("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 сильно упрощает чтение кода. Фактически отступы заставляют разработчика писать аккуратно отформатированный код с четкой визуальной структурой. В более длинных программах Python могут встречаться 66 Глава 4 • Работа со списками блоки кода с отступами нескольких разных уровней. Эти уровни способствуют пониманию общей структуры программы. Когда разработчики только начинают писать код, работа которого зависит от правильности отступов, в их коде нередко встречаются распространенные ошибки. Например, иногда они расставляют отступы в коде, в котором эти отступы не нужны, или наоборот — забывают ставить отступы в блоках, где это необходимо. Несколько примеров помогут вам избежать подобных ошибок в будущем и успеш- но исправлять их, когда они встретятся в ваших программах. Итак, рассмотрим несколько типичных ошибок при использовании отступов. Пропущенный отступ Строка после команды 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("I can't wait to see your next trick, " + magician.title() + ".\n") Команда print в точке должна быть снабжена отступом, но, поскольку Python находит хотя бы одну строку с отступом после команды for , сообщение об ошибке не выдается. В результате первая команда print будет выполнена для каждого Перебор всего списка 67 элемента в списке, потому что в ней есть отступ. Вторая команда 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 выводит сообщение об ошибке, но часто дело ограничивается простой логической ошибкой. Например, что произойдет, если случайно снабдить отступом строку с выводом завершающего приветствия для группы фокусников? magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!") 68 Глава 4 • Работа со списками print("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! Это еще один пример логической ошибки, наподобие описанной в разделе «Про- пущенные отступы в других строках» на с. 66. Python не знает, что вы пытаетесь сделать в своем коде, поэтому он просто выполняет весь код, не нарушающий правил синтаксиса. Если действие, которое должно выполняться один раз, выполняется многократно, проверьте, нет ли лишнего отступа в соответствующей строке кода. Пропущенное двоеточие Двоеточие в конце команды for сообщает Python, что следующая строка является началом цикла. magicians = ['alice', 'david', 'carolina'] for magician in magicians print(magician) Если вы случайно забудете поставить двоеточие, как в примере , произойдет синтаксическая ошибка, так как полученная команда нарушает правила языка. И хотя такие ошибки легко исправляются, найти их бывает достаточно трудно. Вы не поверите, сколько времени тратят программисты на поиск подобных «одно- символьных» ошибок. Поиск таких ошибок усложняется еще и тем, что человек склонен видеть то, что он ожидает увидеть. УПРАЖНЕНИЯ 4-1 . Пицца: вспомните по крайней мере три ваши любимые разновидности пиццы . Сохрани- те их в списке и используйте цикл for для вывода всех названий . • Измените цикл for так, чтобы вместо простого названия пиццы выводилось сообще- ние, включающее это название . Таким образом, для каждого элемента должна выво- диться строка с простым текстом вида «I like pepperoni pizza» . • Добавьте в конец программы (после цикла for) строку с завершающим сообщением . Таким образом, вывод должен состоять из трех (и более) строк с названиями пиццы и дополнительного сообщения, скажем, «I really love pizza!» . Создание числовых списков 69 4-2 . Животные: создайте список из трех (и более) животных, обладающих общей характе- ристикой . Используйте цикл for для вывода названий всех животных . • Измените программу так, чтобы вместо простого названия выводилось сообщение, включающее это название, например «A dog would make a great pet» . • Добавьте в конец программы строку с описанием общего свойства . Например, можно вывести сообщение «Any of these animals would make a great pet!» . Создание числовых списков Необходимость хранения наборов чисел возникает в программах по многим при- чинам. Например, в компьютерной игре могут храниться координаты каждого персонажа на экране, таблицы рекордов и т. д. В программах визуализации данных пользователь почти всегда работает с наборами чисел: температурой, расстоянием, численностью населения, широтой/долготой и другими числовыми данными. Списки идеально подходят для хранения наборов чисел, а Python предоставляет специальные средства для эффективной работы с числовыми списками. Достаточно один раз понять, как эффективно пользоваться этими средствами, и ваш код будет хорошо работать даже в том случае, если список содержит миллионы элементов. Функция range() Функция range() упрощает построение числовых последовательностей. Например, с ее помощью можно легко вывести серию чисел: numbers.py for value in range(1,5): print(value) И хотя на первый взгляд может показаться, что он должен вывести числа от 1 до 5, на самом деле число 5 не выводится: 1 2 3 4 В этом примере range() выводит только числа от 1 до 4. Перед вами еще одно про- явление «смещения на 1», часто встречающегося в языках программирования. При выполнении функции range() Python начинает отсчет от первого переданного зна- чения и прекращает его при достижении второго. Так как на втором значении про- исходит остановка, конец интервала (5 в данном случае) не встречается в выводе. Чтобы вывести числа от 1 до 5, используйте вызов range(1,6) : for value in range(1,6): print(value) На этот раз вывод начинается с 1 и завершается 5: 70 Глава 4 • Работа со списками 1 2 3 4 5 Если ваша программа при использовании range() выводит не тот результат, на который вы рассчитывали, попробуйте увеличить конечное значение на 1. Использование 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) В этом примере функция 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) Создание числовых списков 71 Сначала в точке создается пустой список с именем 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 . Каждое значение в цикле возводится во вторую степень, а затем немедленно присоединя- ется к списку квадратов. При создании более сложных списков можно использовать любой из двух подхо- дов. Иногда использование временной переменной упрощает чтение кода; в других случаях оно приводит лишь к напрасному удлинению кода. Сначала сосредо- точьтесь на написании четкого и понятного кода, который делает именно то, что нужно, — и только потом переходите к анализу кода и поиску более эффективных решений. Простая статистика с числовыми списками Некоторые функции Python предназначены для работы с числовыми списками. Например, вы можете легко узнать минимум, максимум и сумму числового списка: >>> |