为什么Python在list.reverse()上返回None?

问题描述 投票:0回答:4

正在解决算法问题并且必须颠倒列表。 完成后,这就是我的代码的样子:

def construct_path_using_dict(previous_nodes, end_node):
    constructed_path = []
    current_node = end_node
    while current_node:
        constructed_path.append(current_node)
        current_node = previous_nodes[current_node]
    constructed_path = reverse(constructed_path)    
    return constructed_path

但是,一路上,我尝试了

return constructed_path.reverse()
,我意识到它没有返回列表...... 为什么是这样的?
我应该能够直接返回反向列表,而不需要先执行
list.reverse()
list = reverse(list)
,这难道不有意义吗?

python software-design
4个回答
5
投票

我要写的内容已经在这里说过了,但无论如何我都会写它,因为我认为这可能会增加一些清晰度。

您问为什么

reverse
方法不返回(引用)结果,而是就地修改列表。在官方Python教程中,它是这样说的:

您可能已经注意到,插入、删除或排序等仅修改列表的方法没有打印返回值——它们返回默认的 None。这是Python中所有可变数据结构的设计原则。

换句话说(或者至少,这是我的想法) - python 尝试尽可能就地变异(即,在处理不可变数据结构时),以及当它就地变异时,它不会 also 返回对列表的引用 - 因为这样,当它真正返回旧列表时,它看起来会返回一个 new 列表。

需要明确的是,这仅适用于对象methods,而不适用于采用列表的函数,例如,因为该函数无法知道它是否可以改变传入的可迭代对象。

list
还是
tuple
?与对象方法不同,该函数无法知道。


4
投票

list.reverse
原地反转,修改它所调用的列表。一般来说,就地操作的 Python 方法不会返回其操作的内容,以避免混淆返回值是否是副本。

您可以反转并返回原始列表:

constructed_path.reverse()
return constructed_path

或者在原始列表上返回一个反向迭代器,这不是一个列表,但不涉及创建与第一个列表一样大的第二个列表:

return reversed(constructed_path)

或者返回一个包含原始列表反转元素的新列表:

return constructed_path[::-1]
# equivalent: return list(reversed(constructed_path))

如果您不关心性能,只需选择您认为最可读的选项即可。


2
投票

像插入、删除或排序这样只修改列表的方法没有打印返回值——它们返回默认的 None。 1 这是Python中所有可变数据结构的设计原则。

PyDocs 5.1

据我了解,通过比较修改列表(可变)返回的差异,即使用 list.reverse() 并改变作为元组中的元素的列表(不可变),同时调用

,您可以快速看到区别

id(list)

id(tuple_with_list)

突变之前和之后。不返回任何内容的可变数据类型突变是允许它们被更改/扩展/指向多个引用而无需重新分配内存的一部分。


0
投票

我会解释你的问题,因为你想知道为什么

list = [1, 2, 3, 4]
print(list.reverse())

渲染

None

.reverse() 是持久的,并且永久改变[列表]的顺序。

证明这一点的方法是这段代码:

list = [1, 2, 3, 4]
print(list)
print(list.reverse(), list)

给我们

[1, 2, 3, 4]
None [4, 3, 2, 1]

因为首先命令是在 print() 语句中运行,完成后顺序会发生变化,正如我们在上面 None 之后看到的那样。

参考资料: Python官方文档|数据结构 W3学校|蟒蛇 | .reverse()

© www.soinside.com 2019 - 2024. All rights reserved.