为什么我无法在Python中反转列表的列表

11 投票
5 回答
9000 浏览
提问于 2025-04-16 04:35

我想做类似的事情,但这段代码返回的是一个全是 None 的列表(我觉得是因为 list.reverse() 是在原地反转列表的):

map(lambda row: row.reverse(), figure)

我试了这个,但 reversed 返回的是一个迭代器:

map(reversed, figure)

最后我做了这样的事情,这对我有效,但我不知道这是不是正确的解决方案:

def reverse(row):
    """func that reverse a list not in place"""
    row.reverse()
    return row

map(reverse, figure)

如果有人有更好的解决方案,请告诉我。

祝好,

5 个回答

3
reversed_lists = [list(reversed(x)) for x in figure]

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

8

你还可以用切片来反转一个列表(不是原地反转):

>>> 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)

...就能达到你想要的效果。

27

Python中的可变容器(比如列表的.reverse方法)的变更方法几乎总是返回None。虽然有一些方法会返回有用的值,比如.pop方法会返回被弹出的元素,但关键是,这些变更方法并不会返回被改变的容器。相反,容器是在原地发生变化的,变更方法的返回值不是那个容器。(这其实是设计中的一个原则,叫做CQS,虽然在Python中没有那么严格,但这也是因为在Python中“实用性胜过纯粹性”,可以参考import this;-)

构建一个列表通常比仅仅构建一个迭代器要花费更多的资源,尤其是在你只想对结果进行循环的情况下。因此,像reversed这样的内置函数(以及itertools模块中的所有精彩构建块)返回的是迭代器,而不是列表。

但是,如果你有一个迭代器x,但实际上又非常需要一个等效的列表 y呢?这很简单——只需执行y = list(x)。要创建一个新的list类型的实例,你只需调用类型list——这是Python中一个非常普遍的概念,甚至比我在前两段提到的重要内容还要更关键!-)

所以,针对你具体问题的代码其实很容易根据前面段落中的关键概念来组合:

[list(reversed(row)) for row in figure]

注意,我使用的是列表推导式,而不是 map:作为一个经验法则,map应该只在没有lambda的情况下作为最后的优化手段使用(如果涉及到lambda,那么列表推导式通常不仅更清晰,而且速度也更快!-)

一旦你成为了“Python的高手”,如果你的性能分析告诉你这段代码是瓶颈,那么你可以尝试一些替代方案,比如

[row[::-1] for row in figure]

使用负步长切片(也叫“火星微笑”)来创建行的反向副本,因为这通常比list(reversed(row))的方法要快。但是——除非你的代码只打算由你自己或至少同样熟练的Python程序员来维护,否则在没有性能分析的情况下,使用最简单的“从基本原则出发”的方法是一个合理的选择,除非性能分析告诉你需要加速。(我个人认为“火星微笑”在这个特定用例中足够重要,所以我会避免将这种良好的通用哲学应用于此,但合理的人在这个非常具体的点上可能会有不同的看法!-)

撰写回答