Обратные списки Python: Beyond .reverse() и reversed()
Оглавление
- Переворачивание списков Python
- Создание перевернутых списков вручную
- Повторение по спискам в обратном порядке
- Реверсивные списки Python: Краткое изложение
- Сортировка списков Python в обратном порядке
- Заключение
Вы углубляетесь в изучение списков Python и хотите узнать о различных способах их изменения? Если да, то это руководство для вас. Здесь вы узнаете о нескольких инструментах и приемах Python, которые пригодятся, когда дело доходит до изменения списков или манипулирования ими в обратном порядке. Эти знания дополнят и улучшат ваши навыки работы со списками и помогут вам лучше с ними справляться.
В этом руководстве вы узнаете, как:
- Отменить существующие списки на месте, используя
.reverse()и другие методы - Создайте перевернутые копии существующих списков, используя
reversed()и нарезку - Используйте итерацию, повторения и рекурсию для создания обратных списков
- Выполните итерацию по вашим спискам в обратном порядке
- Отсортируйте ваших списков в обратном порядке, используя
.sort()иsorted()
Чтобы извлечь максимальную пользу из этого руководства, было бы полезно ознакомиться с основами итераций, for циклов, списков, понимания списков, генераторные выражения и рекурсия.
Бесплатный бонус: Нажмите здесь, чтобы получить шпаргалку по Python и изучить основы Python 3, такие как работа с типами данных, словари, списки и функции Python.
Реверсирование списков Python
Иногда вам нужно обрабатывать списки Python, начиная с последнего элемента и заканчивая первым — другими словами, в обратном порядке. В целом, существует две основные проблемы, связанные с работой со списками в обратном порядке:
- Изменение существующего списка местами
- Создание измененных копий существующего списка
Для решения первой задачи вы можете использовать либо .reverse(), либо цикл, который меняет местами элементы по индексу. Для второго вы можете использовать reversed() или операцию нарезки. В следующих разделах вы узнаете о различных способах выполнения того и другого в вашем коде.
Измененные списки на месте
Как и другие типы изменяемых последовательностей, списки Python реализуют .reverse(). Этот метод переворачивает базовый список на место для экономии памяти при переворачивании объектов большого списка. Вот как вы можете использовать .reverse():
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> digits.reverse() >>> digits [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>Когда вы вызываете
.reverse()для существующего списка, метод изменяет его на противоположный. Таким образом, при повторном обращении к списку вы получите его в обратном порядке. Обратите внимание, что.reverse()не возвращает новый список, ноNone:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> reversed_digits = digits.reverse() >>> reversed_digits is None Trueпредварительно> кодовый блок>Попытка присвоить возвращаемое значение
.reverse()переменной является распространенной ошибкой, связанной с использованием этого метода. Цель возвратаNoneсостоит в том, чтобы напомнить своим пользователям, что.reverse()работает с помощью побочного эффекта, изменяя базовый список.Примечание: В большинстве примеров в этом руководстве в качестве входных данных используется список из чисел. Однако те же инструменты и методы применимы к спискам объектов Python любого типа, таким как списки строк.
Хорошо! Это было быстро и просто! Итак, как вы можете изменить список вручную? Общепринятый метод заключается в циклическом просмотре первой половины списка, заменяя каждый элемент его зеркальным аналогом во второй половине списка.
Python предоставляет основанные на нуле положительные индексы для перемещения последовательностей слева направо. Он также позволяет перемещаться по последовательностям справа налево, используя отрицательные индексы:
![]()
На этой диаграмме показано, что вы можете получить доступ к первому элементу списка (или последовательности), используя либо
0, либо-5с помощью оператора индексирования, как вsequence[0]иsequence[-5], соответственно. Вы можете использовать эту функцию Python, чтобы изменить базовую последовательность на месте.Например, чтобы перевернуть список, представленный на диаграмме, вы можете выполнить цикл по первой половине списка и поменять местами элемент с индексом
0с его зеркальным отображением с индексом-1на первой итерации. Затем вы можете поменять элемент с индексом1на его зеркальное отображение с индексом-2и так далее, пока не получите перевернутый список.Вот представление всего процесса:
![]()
Чтобы перевести этот процесс в код, вы можете использовать
forцикл с объектомrangeв первой половине списка, который вы можете получить с помощьюlen(digits) // 2. Затем вы можете использовать оператор параллельного присваивания для замены элементов, например, следующим образом:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> for i in range(len(digits) // 2): ... digits[i], digits[-1 - i] = digits[-1 - i], digits[i] ... >>> digits [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>Этот цикл выполняет итерацию по объекту
range, который переходит от0кlen(digits) // 2. Каждая итерация заменяет элемент из первой половины списка на его зеркальный аналог во второй половине. Выражение-1 - i, содержащееся в операторе индексации[], гарантирует доступ к зеркальному элементу. Вы также можете использовать выражение-1 * (i + 1)для получения соответствующего зеркального индекса.Помимо описанного выше алгоритма, который использует преимущества подстановки индекса, существует несколько различных способов изменения списков вручную. Например, вы можете использовать
.pop()и.insert()следующим образом:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> for i in range(len(digits)): ... last_item = digits.pop() ... digits.insert(i, last_item) ... >>> digits [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>В цикле вы вызываете
.pop()для исходного списка без аргументов. Этот вызов удаляет и возвращает последний элемент в списке, поэтому вы можете сохранить его вlast_item. Затем.insert()перемещаетlast_itemна позицию по индексуi.Например, первая итерация удаляет
9из правого конца списка и сохраняет его вlast_item. Затем она вставляет9в индекс0. Следующая итерация берет8и перемещает его в индекс1, и так далее. В конце цикла вы получите перевернутый список.Создание перевернутых списков
Если вы хотите создать обратную копию существующего списка в Python, то вы можете использовать
reversed(). Используя список в качестве аргумента,reversed()возвращает итератор, который возвращает элементы в обратном порядке:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> reversed_digits = reversed(digits) >>> reversed_digits <list_reverseiterator object at 0x7fca9999e790> >>> list(reversed_digits) [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>В этом примере вы вызываете
reversed()сdigitsв качестве аргумента. Затем вы сохраняете результирующий итератор вreversed_digits. Вызовlist()использует итератор и возвращает новый список, содержащий те же элементы, что иdigits, но в обратном порядке.Важно отметить, что при использовании
reversed()не создается копия входного списка, поэтому изменения в нем влияют на результирующий итератор:>>> fruits = ["apple", "banana", "orange"] >>> reversed_fruit = reversed(fruits) # Get the iterator >>> fruits[-1] = "kiwi" # Modify the last item >>> next(reversed_fruit) # The iterator sees the change 'kiwi'предварительно> кодовый блок>В этом примере вы вызываете
reversed(), чтобы получить соответствующий итератор для элементов вfruits. Затем вы изменяете последний результат. Это изменение влияет на итератор. Вы можете подтвердить это, позвонив по телефонуnext()чтобы получить первый товар вreversed_fruit.Если вам нужно получить копию
fruitsс помощьюreversed(), то вы можете позвонитьlist():>>> fruits = ["apple", "banana", "orange"] >>> list(reversed(fruits)) ['orange', 'banana', 'apple']предварительно> кодовый блок>Как вы уже знаете, вызов
list()использует итератор, который является результатом вызоваreversed(). Таким образом, вы создаете новый список как обратную копию исходного.В Python 2.4 добавлен
reversed()универсальный инструмент для облегчения обратной итерации над последовательностями, как указано в ОПТОСОЗ 322. В общем,reversed()может принимать любые объекты, которые реализуют.__reversed__()метод или поддерживают протокол последовательности, состоящий из двух специальных методов,.__len__()и.__getitem__(). Итак,reversed()не ограничивается списками:>>> list(reversed(range(10))) [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] >>> list(reversed("Python")) ['n', 'o', 'h', 't', 'y', 'P']предварительно> кодовый блок>Здесь вместо списка вы передаете объект
rangeи строку в качестве аргументовreversed(). Функция выполняет свою работу должным образом, и вы получаете обратную версию входных данных.Еще один важный момент, который следует подчеркнуть, заключается в том, что вы не можете использовать
reversed()с произвольными итераторами:>>> digits = iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> reversed(digits) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'list_iterator' object is not reversibleпредварительно> кодовый блок>В этом примере,
iter()создает итератор для вашего списка чисел. Когда вы вызываетеreversed()наdigits, вы получаетеTypeError.Итераторы реализуют
.__next__()специальный метод для просмотра базовых данных. Ожидается, что они также будут реализовывать.__iter__()специальный метод, возвращающий текущий экземпляр итератора. Однако ожидается, что они не будут реализовывать ни.__reversed__(), ни протокол последовательности. Таким образом,reversed()для них не работает. Если вам когда-нибудь понадобится изменить итератор подобным образом, вам следует сначала преобразовать его в список, используяlist().Еще один момент, на который следует обратить внимание, заключается в том, что вы не можете использовать
reversed()с неупорядоченными повторяемыми:>>> digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} >>> reversed(digits) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'set' object is not reversibleпредварительно> кодовый блок>В этом примере, когда вы пытаетесь использовать
reversed()с объектомset, вы получаетеTypeError. Это происходит потому, что наборы не упорядочивают свои элементы, поэтому Python не знает, как их изменить.Переворачивание Списков С Помощью Нарезки
Начиная с версии Python 1.4, синтаксис нарезки имеет третий аргумент, который называется
step. Однако этот синтаксис изначально не работал со встроенными типами, такими как списки, кортежи и строки. Python 2.3 расширил синтаксис до встроенных типов, поэтому вы можете использоватьstepс их сейчас. Вот полный синтаксис нарезки:a_list[start:stop:step]предварительно> кодовый блок>Этот синтаксис позволяет извлекать все элементы в
a_listизstartвstop − 1с помощьюstep. Третий индекс,step, по умолчанию равен1, поэтому при обычной операции нарезки элементы извлекаются слева направо:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> digits[1:5] [1, 2, 3, 4]предварительно> кодовый блок>С помощью
[1:5]вы получаете элементы из индекса1в индекс5 - 1. Элемент с индексом, равнымstop, никогда не включается в конечный результат. Эта нарезка возвращает все элементы в целевом диапазоне, потому чтоstepпо умолчанию равно1.Примечание: Вы можете опустить второе двоеточие (
:) в операторе нарезки, если значение по умолчанию (1) соответствует вашим текущим потребностям.Если вы используете другой
step, то при нарезке будет отображаться столько элементов, сколько соответствует значениюstep:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> digits[0::2] [0, 2, 4, 6, 8] >>> digits[::3] [0, 3, 6, 9]предварительно> кодовый блок>В первом примере
[0::2]извлекает все элементы из индекса0до конца индексаdigits, каждый раз перепрыгивая через два элемента. Во втором примере нарезка перемещается по3элементам по мере продвижения. Если вы не указываете значенияstartиstop, то для них устанавливаются значения0и длина целевой последовательности соответственно.Если вы установите для
stepзначение-1, то получите фрагмент с элементами в обратном порядке:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> # Set step to -1 >>> digits[len(digits) - 1::-1] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] >>> digits [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]предварительно> кодовый блок>Это разбиение возвращает все элементы из правого конца списка (
len(digits) - 1) обратно в левый конец, потому что вы опускаете второй индекс. Остальная часть волшебства в этом примере заключается в использовании значения-1дляstep. При выполнении этого трюка вы получаете копию исходного списка в обратном порядке, не затрагивая входные данные.Если вы полностью полагаетесь на неявные индексы, то синтаксис нарезки становится короче, понятнее и менее подвержен ошибкам:
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> # Rely on default index values >>> digits[::-1] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>Здесь вы просите Python предоставить вам полный список (
[::-1]), но просматриваете все элементы от начала до конца, устанавливая дляstepзначение-1. Это довольно изящно, ноreversed()более эффективно с точки зрения времени выполнения и использования памяти. Это также более читабельно и наглядно. Поэтому эти моменты следует учитывать в вашем коде.Другим способом создания обратной копии существующего списка является использование
slice(). Подпись этой встроенной функции выглядит следующим образом:slice(start, stop, step)предварительно> кодовый блок>Эта функция работает аналогично оператору индексирования. Он принимает три аргумента, значение которых аналогично тем, которые используются в операторе slicing, и возвращает объект slice, представляющий набор индексов, возвращаемых
range(start, stop, step). Это звучит сложно, поэтому вот несколько примеров того, как работаетslice():>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> slice(0, len(digits)) slice(0, 10, None) >>> digits[slice(0, len(digits))] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> slice(len(digits) - 1, None, -1) slice(9, None, -1) >>> digits[slice(len(digits) - 1, None, -1)] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>Первый вызов
slice()эквивалентен[0:len(digits)]. Второй вызов работает так же, как и[len(digits) - 1::-1]. Вы также можете имитировать нарезку[::-1]с помощьюslice(None, None, -1). В этом случае передачаNoneвstartиstopозначает, что вам нужен фрагмент от начала до конца целевой последовательности.Примечание: По сути, при разделении литералов создаются
sliceобъектов. Итак, когда вы опускаете индекс, как в[::-1], это работает так, как если бы вы передавалиNoneсоответствующему аргументу при вызовеslice().Вот как вы можете использовать
slice()для создания обратной копии существующего списка:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> digits[slice(None, None, -1)] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>Объект
sliceизвлекает все элементы изdigits, начиная с правого конца и заканчивая левым, и возвращает перевернутую копию целевого списка.Создание перевернутых списков вручную
Итак, вы ознакомились с несколькими инструментами и техниками, позволяющими либо изменять списки на месте, либо создавать обратные копии существующих списков. В большинстве случаев эти инструменты и методы являются наиболее подходящими, когда дело доходит до изменения списков в Python. Однако, если вам когда-нибудь понадобится перевернуть списки вручную, вам будет полезно понять логику, лежащую в основе этого процесса.
В этом разделе вы узнаете, как изменять списки Python с помощью циклов, рекурсии и расширений. Идея заключается в том, чтобы получить список и создать его копию в обратном порядке.
Использование цикла
Первый метод, который вы будете использовать для изменения списка, включает в себя цикл
forи объединение списка с помощью символа плюс (+):>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> def reversed_list(a_list): ... result = [] ... for item in a_list: ... result = [item] + result ... return result ... >>> reversed_list(digits) [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>Каждая итерация цикла
forберет следующий элемент изa_listи создает новый список, который получается в результате объединения[item]иresult, который изначально содержит пустой список. Вновь созданному списку присваивается значениеresult. Эта функция не изменяетa_list.Примечание: В приведенном выше примере используется расточительный метод, поскольку он создает несколько списков только для того, чтобы выбросить их на следующей итерации.
Вы также можете воспользоваться
.insert()для создания перевернутых списков с помощью цикла:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> def reversed_list(a_list): ... result = [] ... for item in a_list: ... result.insert(0, item) ... return result ... >>> reversed_list(digits) [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>Вызов
.insert()внутри цикла вставляет последующие элементы с индексом0, равнымresult. В конце цикла вы получите новый список с элементамиa_listв обратном порядке.Использование
.insert(), как в приведенном выше примере, имеет существенный недостаток. Операции вставки в левом конце списков Python, как известно, неэффективны с точки зрения времени выполнения. Это потому, что Python должен переместить все элементы на шаг назад, чтобы вставить новый элемент в первую позицию.Использование рекурсии
Вы также можете использовать рекурсию для изменения списков. Рекурсия - это когда вы определяете функцию, которая вызывает саму себя. Это создает цикл, который может стать бесконечным, если вы не предоставите базовый вариант , который выдает результат без повторного вызова функции.
Базовый регистр необходим для завершения рекурсивного цикла. Что касается реверсивных списков, базовый регистр будет достигнут, когда рекурсивные вызовы дойдут до конца входного списка. Вам также необходимо определить рекурсивный регистр, который приводит все последующие регистры к базовому регистру и, следовательно, к концу цикла.
Вот как вы можете определить рекурсивную функцию для возврата обратной копии данного списка:
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> def reversed_list(a_list): ... if len(a_list) == 0: # Base case ... return a_list ... else: ... # print(a_list) ... # Recursive case ... return reversed_list(a_list[1:]) + a_list[:1] ... >>> reversed_list(digits) [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>Внутри
reversed_list()вы сначала проверяете базовый вариант, в котором список ввода пуст, и возвращаете функцию. Предложениеelseпредоставляет рекурсивный вариант, который является вызовом самогоreversed_list(), но с фрагментом исходного списка,a_list[1:]. Этот фрагмент содержит все элементы изa_list, за исключением первого элемента, который затем добавляется в виде списка из одного элемента (a_list[:1]) к результату рекурсивного вызова.Примечание: В рекурсивном случае вы можете заменить
a_list[:1]на[a_list[0]], чтобы получить аналогичный результат.Прокомментированный вызов
print()в начале предложенияelse- это просто трюк, предназначенный для того, чтобы показать, как последующие вызовы сокращают список входных данных до базового варианта. Продолжайте и раскомментируйте строку, чтобы посмотреть, что получится!Использование понимания списка
Если вы работаете со списками в Python, то, вероятно, захотите рассмотреть возможность использования понимания списка. Этот инструмент довольно популярен в среде Python, поскольку он представляет собой питонический способ обработки списков.
Вот пример того, как использовать понимание списка для создания перевернутого списка:
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> last_index = len(digits) - 1 >>> [digits[i] for i in range(last_index, -1, -1)] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]предварительно> кодовый блок>Волшебство в понимании этого списка заключается в вызове
range(). В этом случаеrange()возвращает индексы изlen(digits) - 1обратно в0. Это заставляет цикл понимания выполнять итерацию по элементам вdigitsв обратном порядке, создавая в процессе новый перевернутый список.Перебор списков в обратном порядке
На данный момент вы узнали, как создавать перевернутые списки, а также как изменять существующие списки на месте, либо используя инструменты, специально разработанные для выполнения этой задачи, либо используя свои собственные решения, написанные вручную.
При повседневном программировании вы можете обнаружить, что перебор существующих списков и последовательностей в обратном порядке, обычно известный как обратная итерация, является довольно распространенным требованием. Если это ваш случай, то у вас есть несколько вариантов. В зависимости от ваших конкретных потребностей вы можете использовать:
- Встроенная функция
reversed()- Оператор нарезки,
[::]- Специальный метод
.__reversed__()В следующих нескольких разделах вы узнаете обо всех этих параметрах и о том, как они могут помочь вам выполнять итерацию по спискам в обратном порядке.
Встроенная функция
reversed()Первым способом выполнения итерации по списку в обратном порядке может быть использование
reversed(). Эта встроенная функция была специально разработана для поддержки обратной итерации. Используя список в качестве аргумента, он возвращает итератор, который возвращает элементы входного списка в обратном порядке.Вот как вы можете использовать
reversed()для перебора элементов в списке в обратном порядке:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> for digit in reversed(digits): ... print(digit) ... 9 8 7 6 5 4 3 2 1 0предварительно> кодовый блок>Первое, на что следует обратить внимание в этом примере, это то, что цикл
forлегко читается. Названиеreversed()четко выражает его назначение, а тонкие детали указывают на то, что функция не вызывает никаких побочных эффектов. Другими словами, он не изменяет список ввода.Цикл также эффективен с точки зрения использования памяти, поскольку
reversed()возвращает итератор, который выдает элементы по запросу, не сохраняя их все в памяти одновременно. Опять же, следует отметить тонкую деталь: если список входных данных изменяется во время итерации, то итератор видит изменения.Оператор нарезки,
[::-1]Второй подход к обратной итерации заключается в использовании расширенного синтаксиса нарезки, который вы видели ранее. Этот синтаксис никак не способствует повышению эффективности использования памяти, красоты или ясности. Тем не менее, это обеспечивает быстрый способ просмотра обратной копии существующего списка без риска быть затронутым изменениями в исходном списке.
Вот как вы можете использовать
[::-1]для перебора копии существующего списка в обратном порядке:>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> for digit in digits[::-1]: ... print(digit) ... 9 8 7 6 5 4 3 2 1 0предварительно> кодовый блок>Когда вы разрезаете список, как в этом примере, вы создаете обратную копию исходного списка. Изначально оба списка содержат ссылки на одну и ту же группу элементов. Однако, если вы присвоите новое значение данному элементу в исходном списке, как в
digits[0] = "zero", ссылка изменится и будет указывать на новое значение. Таким образом, изменения во входном списке не повлияют на копию.Примечание: По сравнению с расширенной нарезкой,
reversed()более удобочитаем, выполняется быстрее и занимает значительно меньше памяти. Однако на это влияют изменения в списке ввода.Вы можете воспользоваться преимуществами такого рода нарезки, чтобы безопасно изменять исходный список, одновременно перебирая его старые элементы в обратном порядке. Например, предположим, что вам нужно перебрать список чисел в обратном порядке и заменить каждое число его квадратичным значением. В этом случае вы можете сделать что-то вроде этого:
>>> numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> for i, number in enumerate(numbers[::-1]): ... numbers[i] = number ** 2 ... >>> # Square values in reverse order >>> numbers [81, 64, 49, 36, 25, 16, 9, 4, 1, 0]предварительно> кодовый блок>Здесь цикл повторяется по обратной копии
numbers. Вызов функцииenumerate()предоставляет индексы, основанные на возрастании нуля, для каждого элемента в обратной копии. Это позволяет изменятьnumbersво время итерации. Затем цикл изменяетnumbers, заменяя каждый элемент его квадратным значением. В результатеnumbersсодержит квадратные значения в обратном порядке.Специальный метод
.__reversed__()В списках Python реализован специальный метод, называемый
.__reversed__(), который позволяет выполнять обратную итерацию. Этот метод обеспечивает логику, лежащую в основеreversed(). Другими словами, вызовreversed()со списком в качестве аргумента запускает неявный вызов.__reversed__()для входного списка.Этот специальный метод возвращает итератор для элементов текущего списка в обратном порядке. Однако
.__reversed__()не предназначен для прямого использования. В большинстве случаев вы будете использовать его для оснащения своих собственных классов возможностями обратной итерации.Например, предположим, что вы хотите выполнить итерацию по диапазону чисел с плавающей запятой. Вы не можете использовать
range(), поэтому вы решили создать свой собственный класс, соответствующий этому конкретному варианту использования. В итоге вы получаете класс, подобный этому:# float_range.py class FloatRange: def __init__(self, start, stop, step=1.0): if start >= stop: raise ValueError("Invalid range") self.start = start self.stop = stop self.step = step def __iter__(self): n = self.start while n < self.stop: yield n n += self.step def __reversed__(self): n = self.stop - self.step while n >= self.start: yield n n -= self.stepпредварительно> кодовый блок>Этот класс не идеален. Это всего лишь ваша первая версия. Однако он позволяет выполнять итерацию по интервалу чисел с плавающей запятой, используя фиксированное значение приращения
step. В вашем классе,.__iter__()обеспечивает поддержку обычной итерации, а.__reversed__()поддерживает обратную итерацию.Чтобы использовать
FloatRange, вы можете сделать что-то вроде этого:>>> from float_range import FloatRange >>> for number in FloatRange(0.0, 5.0, 0.5): ... print(number) ... 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5предварительно> кодовый блок>Класс поддерживает обычную итерацию, которая, как уже упоминалось, обеспечивается
.__iter__(). Теперь вы можете попробовать выполнить итерацию в обратном порядке, используяreversed():>>> from float_range import FloatRange >>> for number in reversed(FloatRange(0.0, 5.0, 0.5)): ... print(number) ... 4.5 4.0 3.5 3.0 2.5 2.0 1.5 1.0 0.5 0.0предварительно> кодовый блок>В этом примере
reversed()использует вашу реализацию.__reversed__()для обеспечения функциональности обратной итерации. Таким образом, у вас есть работающий итератор с плавающей запятой.Реверсирование списков Python: Краткое изложение
На данный момент вы многое узнали о том, как изменять списки с помощью различных инструментов и техник. Вот таблица, в которой обобщены наиболее важные моменты, которые вы уже рассмотрели:
Feature .reverse()reversed()[::-1]Loop List Comp Recursion Modifies the list in place ✔ ❌ ❌ ✔/❌ ❌ ❌ Creates a copy of the list ❌ ❌ ✔ ✔/❌ ✔ ✔ Is fast ✔ ✔ ❌ ❌ ✔ ❌ Is universal ❌ ✔ ✔ ✔ ✔ ✔ Краткое ознакомление с этим обзором позволит вам решить, какой инструмент или технику использовать при замене существующих списков, создании обратных копий существующих списков или повторном просмотре списков в обратном порядке.
Сортировка списков Python в обратном порядке
Еще один интересный вариант, когда дело доходит до изменения списков в Python, - это использовать
.sort()иsorted()для их сортировки в обратном порядке. Чтобы сделать это, вы можете передатьTrueв соответствующий аргументreverse.Примечание: Чтобы глубже понять, как использовать
.sort()иsorted(), ознакомьтесь с Как использовать sorted() и .sort() в Python..Цель
.sort()- отсортировать элементы списка. Сортировка выполняется на месте, поэтому новый список не создается. Если вы зададите для аргумента ключевого словаreverseзначениеTrue, то получите список, отсортированный в порядке убывания или обратном порядке:>>> digits = [0, 5, 7, 3, 4, 9, 1, 6, 3, 8] >>> digits.sort(reverse=True) >>> digits [9, 8, 7, 6, 5, 4, 3, 3, 1, 0]предварительно> кодовый блок>Теперь ваш список полностью отсортирован, а также в обратном порядке. Это очень удобно, когда вы работаете с некоторыми данными и вам нужно отсортировать их и изменить порядок в обратном порядке одновременно.
С другой стороны, если вы хотите выполнить итерацию по отсортированному списку в обратном порядке, то вы можете использовать
sorted(). Эта встроенная функция возвращает новый список, содержащий все элементы входного итерационного параметра по порядку. Если вы передадитеTrueв его аргумент ключевого словаreverse, то получите обратную копию исходного списка:>>> digits = [0, 5, 7, 3, 4, 9, 1, 6, 3, 8] >>> sorted(digits, reverse=True) [9, 8, 7, 6, 5, 4, 3, 3, 1, 0] >>> for digit in sorted(digits, reverse=True): ... print(digit) ... 9 8 7 6 5 4 3 3 1 0предварительно> кодовый блок>Аргумент
reverseдляsorted()позволяет сортировать повторяющиеся элементы в порядке убывания, а не в порядке возрастания. Итак, если вам нужно создавать отсортированные списки в обратном порядке, тоsorted()для вас.Заключение
Переворачивание и работа со списками в обратном порядке может быть довольно распространенной задачей в вашей повседневной работе в качестве Python программист. В этом руководстве вы воспользовались несколькими инструментами и техниками Python, чтобы изменить свои списки и управлять ими в обратном порядке.
В этом руководстве вы узнали, как:
- Измените местами свои списки , используя
.reverse()и другие методы- Используйте
reversed()и нарезку для создания обратных копий ваших списков- Используйте итерацию, повторения и рекурсию для создания обратных списков
- Выполните итерацию по вашим спискам в обратном порядке
- Отсортируйте списков в обратном порядке, используя
.sort()иsorted()Все эти знания помогут вам улучшить свои навыки работы со списками. Они предоставляют вам необходимые инструменты для повышения квалификации при работе со списками на Python.
<статус завершения article-slug="python-обратный список" class="btn-group mb-0" data-api-article-bookmark-url="/api/v1/articles/python-обратный список/bookmark/" data-api-article-завершение-status-url="/api/v1/articles/python-обратный список/завершение_статуса/"> статус завершения> <кнопка поделиться bluesky-text="Интересная статья на #Python от @realpython.com :" email-body="Ознакомьтесь с этой статьей о Python:%0A%0AReverse Списки Python: Beyond .reverse() и reversised()" email-subject="Статья о Python для вас" twitter-текст="Интересная статья о #Python от @realpython:" url="https://realpython.com/python-reverse-list /" url-title="Обратные списки Python: за пределами .reverse() и reversed()"> кнопка поделиться> Back to Top

