Почему я не могу перевернуть список в Python
Я хотел сделать что-то вроде этого, но этот код возвращает список None (я думаю, это потому, что list.reverse() переворачивает список на месте):
map(lambda row: row.reverse(), figure)
я попробовал это, но обратный возвращает итератор:
map(reversed, figure)
наконец, я сделал что-то вроде этого, что работает для меня, но я не знаю, является ли это правильным решением:
def reverse(row):
"""func that reverse a list not in place"""
row.reverse()
return row
map(reverse, figure)
если у кого-то есть лучшее решение, о котором я не знаю, пожалуйста, дайте мне знать
С уважением,
5 ответов
Методы-мутаторы изменяемых контейнеров Python (такие как .reverse
метод списков) почти всегда возвращают None
- некоторые возвращают одно полезное значение, например .pop
Метод возвращает всплывающий элемент, но ключевая концепция, которую следует сохранить, заключается в том, что ни один из этих мутаторов не возвращает мутированный контейнер: скорее, контейнер мутирует на месте, а возвращаемое значение метода мутатора не является этим контейнером. (Это применение принципа проектирования CQS - не так фанатично, как, скажем, в Eiffel, языке, разработанном Бертраном Мейером, который также изобрел CQS, но это только потому, что в Python "практичность превосходит чистоту, cfr import this
;-).
Построение списка часто обходится дороже, чем просто создание итератора, поскольку в подавляющем большинстве случаев все, что вы хотите сделать, это зациклить результат; поэтому встроенные модули, такие как reversed
(и все замечательные строительные блоки в itertools
модуль) возвращают итераторы, а не списки.
Но что, если у вас есть итератор? x
но на самом деле действительно нужен эквивалентный список y
? Кусок торта - просто сделай y = list(x)
, Чтобы сделать новый экземпляр типа list
Вы называете тип list
- это такая общая идея Python, что даже более важно сохранить, чем довольно важный материал, который я указал в первых двух абзацах!-)
Таким образом, код для вашей конкретной проблемы действительно очень легко собрать, основываясь на ключевых понятиях в предыдущих параграфах:
[list(reversed(row)) for row in figure]
Обратите внимание, что я использую понимание списка, а не map
: как правило большого пальца, map
следует использовать только в качестве последней оптимизации, когда нет необходимости lambda
построить его (если lambda
Это значит, что listcomp, как и обычно, яснее, в любом случае, как правило, быстрее!-).
Как только вы станете "бывшим мастером Python", если ваше профилирование говорит вам, что этот код является узким местом, вы можете попробовать альтернативные варианты, такие как
[row[::-1] for row in figure]
применяя нарезку отрицательного шага (также известный как "Марсианский смайлик"), чтобы сделать обратные копии строк, зная, что обычно это быстрее, чем list(reversed(row))
подход. Но - если ваш код не предназначен для поддержки только вами или кем-то, по крайней мере, столь же опытным в Python - это оправданная позиция, чтобы использовать простейший подход "код из первых принципов", за исключением случаев, когда профилирование говорит вам нажать на педаль, (Лично я думаю, что "Марсианский смайлик" достаточно важен, чтобы не применять эту хорошую общую философию к этому конкретному случаю использования, но, эй, разумные люди могут отличаться по этому очень специфическому вопросу!-).
Вы также можете использовать срез, чтобы получить реверс одного списка (не на месте):
>>> a = [1,2,3,4]
>>> a[::-1]
[4, 3, 2, 1]
Так что-то вроде:
all_reversed = [lst[::-1] for lst in figure]
...или же...
all_reversed = map(lambda x: x[::-1], figure)
... будет делать то, что вы хотите.
Вы также можете просто сделать
for row in figure:
row.reverse()
изменить каждый ряд на месте.