Изучаем 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.
|
56 Глава 3 • Списки Удаление элемента с использованием метода pop() Иногда значение, удаляемое из списка, должно как-то использоваться. Допустим, вы хотите получить координаты x и y только что сбитого корабля пришельцев, что- бы изобразить взрыв в этой позиции. В веб-приложении пользователь, удаленный из списка активных участников, может быть добавлен в список неактивных, и т. д. Метод pop() удаляет последний элемент из списка, но позволяет работать с ним после удаления. Удалим мотоцикл из списка: ❶ motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles) ❷ popped_motorcycle = motorcycles.pop() ❸ print(motorcycles) ❹ print(popped_motorcycle) Сначала в точке определяется и выводится содержимое списка motorcycles В точке значение извлекается из списка и сохраняется в переменной с именем popped_motorcycle . Вывод измененного списка в точке показывает, что значе- ние было удалено из списка. Затем мы выводим извлеченное значение в точке , демонстрируя, что удаленное из списка значение остается доступным в программе. Из вывода видно, что значение 'suzuki' , удаленное в конце списка, теперь хранится в переменной popped_motorcycle : ['honda', 'yamaha', 'suzuki'] ['honda', 'yamaha'] suzuki Для чего может понадобиться метод pop() ? Представьте, что мотоциклы в списке хранятся в хронологическом порядке в соответствии с датой их покупки. В таком случае команда pop() может использоваться для вывода сообщения о последнем купленном мотоцикле: motorcycles = ['honda', 'yamaha', 'suzuki'] last_owned = motorcycles.pop() print(f"The last motorcycle I owned was a {last_owned.title()}.") Программа выводит простое сообщение: The last motorcycle I owned was a Suzuki. Извлечение элементов из произвольной позиции списка Вызов pop() может использоваться для удаления элемента в произвольной позиции списка; для этого следует указать индекс удаляемого элемента в круглых скобках. motorcycles = ['honda', 'yamaha', 'suzuki'] ❶ first_owned = motorcycles.pop(0) ❷ print(f"The first motorcycle I owned was a {first_owned.title()}.") Изменение, добавление и удаление элементов 57 Сначала первый элемент извлекается из списка в точке , а затем в точке вы- водится сообщение об этом мотоцикле. Программа выводит простое сообщение о первом мотоцикле: The first motorcycle I owned was a Honda. Помните, что после каждого вызова pop() элемент, с которым вы работаете, уже не находится в списке. Если вы не уверены в том, какой из двух способов выбрать, команду del или метод pop() , — простое правило поможет вам определиться: если вы собираетесь просто удалить элемент из списка, никак не используя его, выбирайте команду del ; если же вы намерены использовать элемент после удаления из списка, выбирайте ме- тод pop() Удаление элементов по значению Иногда позиция удаляемого элемента неизвестна. Если вы знаете только значение элемента, используйте метод remove() Допустим, из списка нужно удалить значение 'ducati' : motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati'] print(motorcycles) ❶ motorcycles.remove('ducati') print(motorcycles) Код в точке приказывает Python определить, в какой позиции списка находится значение 'ducati' , и удалить этот элемент: ['honda', 'yamaha', 'suzuki', 'ducati'] ['honda', 'yamaha', 'suzuki'] Метод remove() также может использоваться для работы со значением, которое удаляется из списка. Следующая программа удаляет значение 'ducati' и выводит причину удаления: ❶ motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati'] print(motorcycles) ❷ too_expensive = 'ducati' ❸ motorcycles.remove(too_expensive) print(motorcycles) ❹ print(f"\nA {too_expensive.title()} is too expensive for me.") После определения списка в точке значение 'ducati' сохраняется в перемен- ной с именем too_expensive в точке . Затем эта переменная сообщает Python, какое значение должно быть удалено из списка . В точке значение 'ducati' было удалено из списка, но продолжает храниться в переменной too_expensive , 58 Глава 3 • Списки что позволяет вывести сообщение с причиной удаления 'ducati' из списка мо- тоциклов: ['honda', 'yamaha', 'suzuki', 'ducati'] ['honda', 'yamaha', 'suzuki'] A Ducati is too expensive for me. ПРИМЕЧАНИЕ Метод remove() удаляет только первое вхождение заданного значе- ния . Если существует вероятность того, что значение встречается в списке более одного раза, используйте цикл для определения того, были ли удалены все вхождения данного значения . О том, как это делать, рассказано в главе 7 . УПРАЖНЕНИЯ Следующие упражнения немного сложнее упражнений из главы 2, но они предоставляют возможность попрактиковаться в выполнении всех описанных операций со списками. 3.4. Список гостей: если бы вы могли пригласить кого угодно (из живых или умерших) на обед, то кого бы вы пригласили? Создайте список, включающий минимум трех людей, которых вам хотелось бы пригласить на обед. Затем используйте этот список для вывода пригласительного сообщения каждому участнику. 3.5. Изменение списка гостей: вы только что узнали, что один из гостей прийти не сможет, поэтому вам придется разослать новые приглашения. Отсутствующего гостя нужно заме- нить кем-то другим. • Начните с программы из упражнения 3.4. Добавьте в конец программы команду print для вывода имени гостя, который прийти не сможет. • Измените список и замените имя гостя, который прийти не сможет, именем нового приглашенного. • Выведите новый набор сообщений с приглашениями — по одному для каждого участника, входящего в список. 3.6. Больше гостей: вы решили купить обеденный стол большего размера. Дополнитель- ные места позволяют пригласить на обед еще трех гостей. • Начните с программы из упражнения 3.4 или 3.5. Добавьте в конец программы коман ду print , которая выводит сообщение о расширении списка гостей. • Добавьте вызов insert() для добавления одного гостя в начало списка. • Добавьте вызов insert() для добавления одного гостя в середину списка. • Добавьте вызов append() для добавления одного гостя в конец списка. • Выведите новый набор сообщений с приглашениями — по одному для каждого участника, входящего в список. 3.7. Сокращение списка гостей: только что выяснилось, что новый обеденный стол при- везти вовремя не успеют и места хватит только для двух гостей. • Начните с программы из упражнения 3.6. Добавьте команду для вывода сообщения о том, что на обед приглашаются всего два гостя. • Используйте метод pop() для последовательного удаления гостей из списка до тех пор, пока в списке не останутся только два человека. Каждый раз, когда из списка удаляется очередное имя, выведите для этого человека сообщение о том, что вы со- жалеете об отмене приглашения. Упорядочение списка 59 • Выведите сообщение для каждого из двух человек, остающихся в списке. Сообще- ние должно подтверждать, что более раннее приглашение остается в силе. • Используйте команду del для удаления двух последних имен, чтобы список остался пустым. Выведите список, чтобы убедиться в том, что в конце работы программы список действительно не содержит ни одного элемента. Упорядочение списка Нередко список создается в непредсказуемом порядке, потому что порядок полу- чения данных от пользователя не всегда находится под вашим контролем. И хотя во многих случаях такое положение дел неизбежно, часто требуется вывести инфор- мацию в определенном порядке. В одних случаях требуется сохранить исходный порядок элементов в списке, в других исходный порядок должен быть изменен. Python предоставляет в распоряжение программиста несколько разных способов упорядочения списка в зависимости от ситуации. Постоянная сортировка списка методом sort() Метод sort() позволяет относительно легко отсортировать список. Предположим, имеется список машин и вы хотите переупорядочить эти элементы по алфавиту. Чтобы упростить задачу, предположим, что все значения в списке состоят из сим- волов нижнего регистра. cars.py cars = ['bmw', 'audi', 'toyota', 'subaru'] ❶ cars.sort() print(cars) Метод sort() в точке осуществляет постоянное изменение порядка элементов в списке. Названия машин располагаются в алфавитном порядке, и вернуться к ис- ходному порядку уже не удастся: ['audi', 'bmw', 'subaru', 'toyota'] Список также можно отсортировать в обратном алфавитном порядке; для этого методу sort() следует передать аргумент reverse=True . В следующем примере список сортируется в порядке, обратном алфавитному: cars = ['bmw', 'audi', 'toyota', 'subaru'] cars.sort(reverse=True) print(cars) И снова порядок элементов изменяется на постоянной основе: ['toyota', 'subaru', 'bmw', 'audi'] 60 Глава 3 • Списки Временная сортировка списка функцией sorted() Чтобы сохранить исходный порядок элементов списка, но временно представить их в отсортированном порядке, можно воспользоваться функцией sorted() . Функция sorted() позволяет представить список в определенном порядке, но не изменяет фактический порядок элементов в списке. Попробуем применить эту функцию к списку машин. cars = ['bmw', 'audi', 'toyota', 'subaru'] ❶ print("Here is the original list:") print(cars) ❷ print("\nHere is the sorted list:") print(sorted(cars)) ❸ print("\nHere is the original list again:") print(cars) Сначала список выводится в исходном порядке , а затем в алфавитном порядке . После того как список будет выведен в новом порядке, в точке мы убеждаемся в том, что список все еще хранится в исходном порядке. Here is the original list: ['bmw', 'audi', 'toyota', 'subaru'] Here is the sorted list: ['audi', 'bmw', 'subaru', 'toyota'] ❹ Here is the original list again: ['bmw', 'audi', 'toyota', 'subaru'] Обратите внимание: после вызова функции sorted() список продолжает хранить- ся в исходном порядке . Функции sorted() также можно передать аргумент reverse=True , чтобы список был представлен в порядке, обратном алфавитному. ПРИМЕЧАНИЕ Если не все значения записаны в нижнем регистре, алфавитная сорти- ровка списка немного усложняется . При определении порядка сортировки появляются разные способы интерпретации прописных букв, и точное определение порядка уже не столь тривиально (во всяком случае, чтобы отвлекаться на него сейчас) . Впрочем, большинство способов сортировки напрямую следует из того, о чем вы узнали в этом разделе . Вывод списка в обратном порядке Чтобы переставить элементы списка в обратном порядке, используйте метод reverse() . Скажем, если список машин первоначально хранился в хронологиче- ском порядке даты приобретения, элементы можно легко переупорядочить в об- ратном хронологическом порядке: Упорядочение списка 61 cars = ['bmw', 'audi', 'toyota', 'subaru'] print(cars) cars.reverse() print(cars) Обратите внимание: метод reverse() не сортирует элементы в обратном алфавит- ном порядке, а просто переходит к обратному порядку списка: ['bmw', 'audi', 'toyota', 'subaru'] ['subaru', 'toyota', 'audi', 'bmw'] Метод reverse() осуществляет постоянное изменение порядка элементов, но вы можете легко вернуться к исходному порядку, снова применив reverse() к обрат- ному списку. Определение длины списка Вы можете быстро определить длину списка с помощью функции len() . Список в нашем примере состоит из четырех элементов, поэтому его длина равна 4: >>> cars = ['bmw', 'audi', 'toyota', 'subaru'] >>> len(cars) 4 Метод len() может пригодиться для определения количества пришельцев, кото- рых необходимо сбить в игре; объема данных, которыми необходимо управлять в визуализации; количества зарегистрированных пользователей на веб-сайте и т. д. ПРИМЕЧАНИЕ Python подсчитывает элементы списка, начиная с 1, поэтому при опре- делении длины списка ошибок «смещения на 1» уже быть не должно . УПРАЖНЕНИЯ 3.8. Повидать мир: вспомните хотя бы пять стран, в которых вам хотелось бы побывать. • Сохраните названия стран в списке. Проследите за тем, чтобы список не хранился в алфавитном порядке. • Выведите список в исходном порядке. Не беспокойтесь об оформлении, просто вы- ведите его как обычный список Python. • Используйте функцию sorted() для вывода списка в алфавитном порядке без из- менения списка. • Снова выведите список, чтобы показать, что он по-прежнему хранится в исходном порядке. • Используйте функцию sorted() для вывода списка в обратном алфавитном порядке без изменения порядка исходного списка. • Снова выведите список, чтобы показать, что исходный порядок не изменился. • Измените порядок элементов вызовом reverse() . Выведите список, чтобы показать, что элементы следуют в другом порядке. 62 Глава 3 • Списки • Измените порядок элементов повторным вызовом reverse() . Выведите список, что- бы показать, что список вернулся к исходному порядку. • Отсортируйте список в алфавитном порядке вызовом sort() . Выведите список, что- бы показать, что элементы следуют в другом порядке. • Вызовите sort() для перестановки элементов списка в обратном алфавитном по- рядке. Выведите список, чтобы показать, что порядок элементов изменился. 3.9. Количество гостей: в одной из программ из упражнений с 3.4 по 3.7 используйте len() для вывода сообщения с количеством людей, приглашенных на обед. 3.10. Все функции: придумайте информацию, которую можно было бы хранить в списке. Например, создайте список гор, рек, стран, городов, языков… словом, чего угодно. Напи- шите программу, которая создает список элементов, а затем вызывает каждую функцию, упоминавшуюся в этой главе, хотя бы один раз. Ошибки индексирования при работе со списками Когда программист только начинает работать со списками, он часто допускает одну характерную ошибку. Допустим, имеется список с тремя элементами и программа запрашивает четвертый элемент: motorcycles.py motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles[3]) В этом случае происходит ошибка индексирования: Traceback (most recent call last): File "motorcycles.py", line 3, in print(motorcycles[3]) IndexError: list index out of range Python пытается вернуть элемент с индексом 3. Однако при поиске по списку ни один элемент motorcycles не обладает индексом 3. Из-за смещения индексов на 1 эта ошибка весьма распространена. Люди думают, что третьим элементом является элемент с индексом 3, потому что они начинают отсчет с 1. Но для Python третьим является элемент с индексом 2, потому что индексирование на- чинается с 0. Ошибка индексирования означает, что Python не может понять, какой индекс за- прашивается в программе. Если в вашей программе происходит ошибка индексиро- вания, попробуйте уменьшить запрашиваемый индекс на 1. Затем снова запустите программу и проверьте правильность результатов. Помните, что для обращения к последнему элементу в списке используется ин- декс –1. Этот способ работает всегда, даже если размер списка изменился с момента последнего обращения к нему: motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles[-1]) Итоги 63 Индекс –1 всегда возвращает последний элемент списка, в данном случае значе- ние 'suzuki' : 'suzuki' Этот синтаксис порождает ошибку только в одном случае — при попытке получить последний элемент пустого списка: motorcycles = [] print(motorcycles[-1]) В списке motorcycles нет ни одного элемента, поэтому Python снова выдает ошибку индексирования: Traceback (most recent call last): File "motorcyles.py", line 3, in IndexError: list index out of range ПРИМЕЧАНИЕ Если в вашей программе произошла ошибка индексирования и вы не знаете, как с ней справиться, попробуйте вывести список или хотя бы его длину . Воз- можно, ваш список выглядит совсем не так, как вы думаете, особенно если его содержи- мое динамически определялось программой . Фактическое состояние списка или точное количество элементов в нем поможет вам выявить логические ошибки такого рода . УПРАЖНЕНИЯ 3.11. Намеренная ошибка: если ни в одной из предшествующих программ вы еще не стал- кивались с ошибками индексирования, попробуйте создать такую ошибку искусственно. Измените индекс в одной из программ, чтобы вызвать ошибку индексирования. Не забудь- те исправить ошибку перед тем, как закрывать программу. Итоги В этой главе вы узнали, что собой представляют списки и как работать с отдельны- ми элементами в списках. Вы научились определять списки, добавлять и удалять элементы, выполнять сортировку (постоянную или временную для отображения). Также вы узнали, как определить длину списка и как избежать ошибок индексиро- вания при работе со списком. В главе 4 рассматриваются приемы более эффективной работы со списками. Пере- бор всех элементов списка всего в нескольких строках кода, даже если список со- держит тысячи или миллионы элементов, сокращает объем программы. 4 Работа со списками В главе 3 вы научились создавать простые списки и работать с отдельными эле- ментами списков. В этой главе вы узнаете, как перебрать весь список в нескольких строках кода (независимо от длины списка). Механизм перебора позволяет вы- полнить одно действие или набор действий с каждым элементом в списке. С его помощью вы сможете эффективно работать со списками любой длины, даже со- стоящими из тысяч и миллионов элементов. Перебор всего списка Типичная задача из области программирования — перебрать все элементы списка и выполнить с каждым элементом одну и ту же операцию. Например, в компью- терной игре все экранные объекты могут смещаться на одинаковую величину или в списке чисел к каждому элементу может применяться одна и та же статистиче- ская операция. А может быть, вам потребовалось вывести все заголовки из списка статей на сайте. В ситуациях, требующих применения одного действия к каждому элементу списка, можно воспользоваться циклами for Допустим, имеется список с именами фокусников и вы хотите вывести каждое имя из списка. Конечно, можно обратиться к каждому элементу по отдельности, но та- кой подход создает ряд проблем. Во-первых, для очень длинных списков все сведет- ся к однообразным повторениям. Во-вторых, при любом изменении длины списка в программу придется вносить изменения. Цикл for решает обе проблемы: Python будет следить за всеми техническими деталями в своей внутренней реализации. В следующем примере цикл for используется для вывода имен фокусников: |