Почему я не могу перевернуть список в 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)

... будет делать то, что вы хотите.

reversed_lists = [list(reversed(x)) for x in figure]
map(lambda row: list(reversed(row)), figure)

Вы также можете просто сделать

for row in figure:
    row.reverse()

изменить каждый ряд на месте.

Другие вопросы по тегам