Саммерфилд - Программирование на Python 3 (1077331), страница 37
Текст из файла (страница 37)
Затем создается список лет— путем создания списка со значениями в диапазоне от 1970 до 2012 включительно, после чего этот список дублируется трижды, поэтому в окончательном списке каждый год встречается три раза. Это необходимо потому, что функция гапоае, ваер1е() (используемая вместо гапОае. сла(се()) принимает итерируемый объект и число элементов, которые требуется воспроизвести — это число не может быть меньше, чем число элементов, которые может вернуть итерируемый объект. Функция гапоае.
ваер1е( ) возвращает итератор, который воспроизводит указанное число элементов без повторений. Поэтому данная версия программы всегда будет воспроизводить уникальные имена. о В цикле Гаг ... (п распаковывается каждый кортеж, Распакавывакквкартаева возвращаемый функцией 2(р(). Нам требуется огранистр.133 чить длину каждого имени 25 символами, а для этого сначала нужно создать строку с полным именем, а затем вторым вызовом метода втг, Гагеат() ограничить ее дли- о ну. Каждое имя выравнивается по левому краю, адля метал всг имен короче 25 символов производится дополнение стростр. 100 ки точками.
Дополнительная точка гарантирует, что имена, полностью занимающие поле вывода„все же будут отделяться от года хотя бы одной точкой. В завершение этого подраздела мы упомянем еще две функции, имеющие отношение к итерируемым объектам — вагте0() и гечегвео(). Функция вагтеа() возвращает отсортированный список элементов, а функция гечегвеа() просто возвращает итератор, который позволяет выполнить обход элементов заданного итератора в обратном порядке. Ниже приводится пример использования функции гече гвео( ): »> 11ы( гапав(6) ) (О, 1, 2, 3, 4, 5] »> 11вт(гечвгвва(гапае(6))) [5 4, 3, 2, 1, 0] Функция вагтеп() — более сложная, как показано в примере ниже: »> х = (] »> таг т тп а1р(гапае(-10, О, 1), гапав(0, 1О, 2), гапае(1, 10, 2)): Обход з цикле и копирование коллекций 141 х»= с »> х [10,0,1,-9,2,3,-8,4,5,-7,6,7,-6,8,9] »> аогсес(х) [-10, -9, -8, -7.
-б, О, 1, 2, 3, 4, 5, б, 7, 8, 9] »> аогСеп(х, гачегае=тгие) [9, 8. 7, б, 5, 4, 3, 2, 1, О, -6, -7, -8, -9, - 10] »> аогСеа(х, Кау=аза) (О, 1, 2, 3, 4, 5, б, -6, -7, 7, -8, 8, -9, 9, - 10 ] В предыдущем фрагменте функция 2ср() возвращает кортежи, состоящиеизтрех элементов: (-10, О, 1), (-9, 2, 3) ит.д. Оператор«=дополняет список, то есть добавляет каждый элемент заданной последовательности в конец списка. Первый вызов функции аогСеб() возвращает копию списка, отсортированную в привычном порядке. Второй вызов возвращает копию списка, отсортированную в обратном порядке. В последнем вызове функции аогСес() определена функция «]сеу», к которой мы вернемся через несколько мгновений.
Обратите внимание, что в языке РуСЬоп функции являются самыми обычными объектами, поэтому они могут передаваться другим функциям в виде аргументов и сохраняться в коллекциях без излишних формальностей. Не забывайте, что имя функции — это ссылка на объект функции, а круглые скобки, следующие за именем, сообщают интерпретатору РуФЬоп о необходимости вызова этой функции. Когда функции аогСеб() передается функция Кеу (в данном случае— функция аоз()), она будет вызываться для каждого элемента списка (каждый элемент будет передаваться функции в виде единственного аргумента), чтобы создать «декорированный» список.
Затем выполняется сортировка декорированного списка, после чего в качестве результата возвращается недекорированный список. Мы легко можем использовать собственные функции в качестве аргумента Кеу, в чем вы вскоре убедитесь. Например, мы можем выполнить сортировку без учета регистра символов, передав в аргументе Кеу метод 81г.1оиег(). Если представить, что унас имеется список [ "9[сор", "уаи1", "СОССег", "асаоопег", "Ке(ОЛ" ], мы можем отсортировать его без учета регистра символов, используя ВЯ(]-сортировку (Весогабе, Яогб, (]пс[есогабе — декорирование, сортировка, обратное декорирование), всего одной строкой программного кода, передав нужную функцию в аргументе Кеу или выполнив сортировку явно, как показано в следующих двух эквивалентных фрагментах программного кода: сепр = [] Гог 1СЕВ сл Х: сеэр.
аррепс(( 1сеэ. 1о«ег( ), 1сеп) ) Глава 3. Типы коллекций х = [] Гсг Кеу, ча1се сп всгсес(Севр): х.аррасе(ча1ие) х = всгсее(х, кеу=всг. 1счег) Оба фрагмента воспроизводят новый список: [ "Сс((ег", "Ке(сп", "вспоопег", "51оор", "Уаи1" ], хотя действия, которые они выполняют, не идентичны, потому что во фрагменте справа создается промежуточный список сеар.
В языке РуСЬоп реализован адаптивный алгоритм устойчивой сортировки со слиянием, который отличаетея высокой скоростью и интеллектуальностью и особенно хорошо подходит для сортировки частично отсортированных списков, что встречается достаточно часто.' Слово «адаптивный» в названии алгоритма означает, что алгоритм сортировки адаптируется под определенные условия, например, учитывает наличие частичной сортировки данных.
Слово «устойчивый» означает, что одинаковые элементы не перемещаются относительно друг друга (в конце концов, в этом нет никакой необходимости), и слова «сортировка со слиянием» вЂ” это общее название используемых алгоритмов сортировки. Когда выполняетея сортировка списка целых чисел, строк или данных других простых типов, используется оператор «меньше чем» (<). Интерпретатор РуС)соп может сортировать коллекции, содержащие другие коллекции, выполняя рекурсивный спуск на произвольную глубину. Например: »> х = 1(вС(ыр((1, 3, 1, 3), ("ргав", "Есгсе", "КауаК", 'сапсе"))) >» х [(1, ргаа'), (3, 'асгсе'), (1, 'КауаК'), (3, 'сапсе')] »> всгсее(х) [(1, 'кауак'), (1, ргае'), (3, 'сааре'), (3, 'есгсе')] РуСЬоп отсортировал список кортежей, сравнив сначала первые элементы каждого кортежа, а если они были равны — вторые элементы.
В результате элементы были отсортированы на основе целых чисел, с использованием строк для дополнительной сортировки. Мы можем принудительно сначала отсортировать список по строкам, а дополнительную сортировку выполнить по целым числам, определив простую функцию, которая будет использоваться в качестве аргумента Кеу: сег виар(с): гессгп с[11, с[0] Функция виар( ) принимает кортеж из двух элементов и возвращает новый кортеж из двух элементов, в котором элементы переставлены местами. Представим, что функцию виар() мы ввели в среде ШЬЕ, тогда можно выполнить следующее: Алгоритм был создан Тимом Петерсом (Тпп Ре(егв). Интересное описание и обсуждение алгоритма можно найти в файле!иг«огшхц который поставляется в составе исходных программных кодов Ру()соп. Обход в цикле и копирование коллекций 173 »> зогтеб(х, Кеу=зиар) [(3, 'сапое'), (3, 'бог(е'), (1, 'КауаК'), (1, 'ргаю')] Кроме того, списки могут быть отсортированы непосредственно, без создания копии, с помощью метода 11зс.
во гс(), который принимает те же необязательные аргументы, что и функция вогсеб(). Сортировка может применяться только к коллекциям, все элементы которых могут сравниваться друг с другом: зогтеб([3, 8, -7.5, О, 1.3]) а вернет; [-7 5, О, 1. 3, 3, 8] зогсео([3, "зраппег", -7.5, О, 1.3]) 4 возбудит исключение турееггог зогСеб(["1.3", -7.5. "5", 4, "-2.4", 1], Кеу=Г1оат) Этовыражениевернетсписок[-7.3, '-2.4', 1, '1.3', 4, '5'].Обратите внимание, что значения в списке не изменились, то есть строки так и остались строками.
Если какая-либо строка не сможет быть преобразована в число (например, "враппег"), будет возбуждено исключение ТуреЕ г го г. Копированиеколлекций Поскольку в языке Руб]соп повсюду используются ссылки на объекты, когда выполняется оператор присваивания (=), никакого копирования данных на самом деле не происходит. Если справа от оператора находится литерал, например, строка или число, в операнд слева записывается ссылка, которая указывает на объект в памяти, хранящий значение литерала. Если справа находится ссылка на объект, в левый операнд записывается ссылка, указывающая на тот же самый объект, на который ссылается правый операнд. Вследствие этого операция присваивания обладает чрезвычайно высокой скоростью выполнения. а Ссылки иа объекты, стр.
29 Когда выполняется присваивание крупной коллекции, такой как длинный список, экономия времени становится более чем очевидной. Например: »> зопдз = ["Весаозе", "Воуз", "Саго1"] »> ЬеаС1ез = зопдз Хотя первый список содержит числа разных типов (1пт и 71оат), тем не менее эти типы могут сравниваться друг с другом, поэтому сортировка к такому списку вполне применима. Но во втором списке содержится строка, которую не имеет смысла сравнивать с числами, поэтому возбуждается исключение ТуреЕггог. Если необходимо отсортировать список, содержащий целые числа, числа с плавающей точкой и строки, представляющие числа, можно попробовать передать в аргументе Кеу функцию 71оаС()с 174 Глава 3. Типы коллекций »> ЬваС1вв, вапдв (['Веааавв', 'Вауз', 'Сага1'], ['Ввааавв', 'Ваув', 'Сага1']) Здесь была создана новая ссылка на объект (ЬеаС1ез), и обе ссылки указывают на один и тот же список — никакого копирования данных не производилось.
Поскольку списки относятся к категории изменяемых объектов, мы можем вносить в них изменения. Например: »> ЬваС1вв[2] = "Сауеппе" »> ьеас1вв, вапдв (['Весаавв', 'Ваув', 'Саувппв'], ['Весаавв', 'Ваув', 'Саувппа']) Изменения были внесены с использованием переменной ЬеаС1ев, но это всего лишь ссылка, указывающая на тот же самый объект, что и ссылка вапдв. Поэтому любые изменения, произведенные с использованием одной ссылки, можно наблюдать с использованием другой ссылки.
Часто это именно то, что нам требуется, поскольку копирование крупных коллекций может оказаться дорогостоящей операцией. Кроме того, это также означает, что имеется возможность передавать списки или другие изменяемые коллекции в виде аргументов функций, изменять зти коллекции в функциях и пребывать в уверенности, что изменения будут доступны после того, как функция вернет управление вызывающей программе.