反转元组和反转列表有什么区别?

20

翻转元组和翻转列表会返回不同类型的对象:

>>> reversed((1,2))
<reversed at 0x7fffe802f748>
>>> reversed([1,2])
<list_reverseiterator at 0x7fffebdd4400>

它们具有相同的dir属性。两种类型都不是彼此的子类。

为什么会这样?其中一种类型可以做什么另一种不能做?


除非您使用的是旧版本的python,在listreverseiterator上调用len,否则似乎没有任何性能差异。http://bugs.python.org/issue3689。 - Padraic Cunningham
2个回答

14

基本上,列表实现了__reversed__方法并返回一个特定的对象,而tuple对于任何序列都会回退到reversed的默认实现:

>>> list.__reversed__
<method '__reversed__' of 'list' objects>
>>> tuple.__reversed__
AttributeError: type object 'tuple' has no attribute '__reversed__'

现在,为什么列表不默认使用倒序的reversed对象,必须在列表对象的源代码中找到答案 - 可能它通过直接访问一些内部list属性来启用一些优化。

实际上,在查看了C代码之后,几乎没有区别,当然也没有引起注意的地方 -

我敢说特殊的列表__reversed__实现是Python2时代的遗留问题,因为reversed实际上会将任何其他Python序列复制到一个list中 - 所以对于其他序列来说,没有理由为其设置特殊情况(而当他们确实实现了通用的enumreverse时,对于元组来说已经足够好了)。

我非常确定,如果在listobject.c上注释掉__reversed__插槽,Python和它的列表将像什么都没发生一样工作,使用通用情况下的reversed


3
默认反向:https://github.com/python/cpython/blob/master/Objects/enumobject.c#L230 列表反向:https://github.com/python/cpython/blob/master/Objects/listobject.c#L2823 - BlackBear
3
彼此之间有哪些不同的能力或特点呢? - wim
5
Github 专业提示: 如果你像这样链接到 blob/master 中的行号,一旦文件被修改,链接就会失效。相反,选择你想要的行数,然后按 y 键将链接固定到特定提交。然后行号将永远不会偏离相关代码。我已经更新了你回答中的链接。 - wim
@wim 谢谢。我今天才知道 'y' 这个命令。我之前知道链接失效的问题,但一直都是手动查找提交记录。 - Mad Physicist
因为list可变,是否有任何理由拥有不同类型的迭代器呢? - Mad Physicist

5
根据Python的文档

object.__reversed__(self)

如果存在,则被reversed()内置函数调用以实现反向迭代。它应该返回一个新的迭代器对象,该对象以相反的顺序迭代容器中的所有对象。

如果未提供__reversed__()方法,则reversed()内置函数将回退到使用序列协议(__len__()__getitem__())。支持序列协议的对象应仅在能够提供比reversed()提供的更有效的实现时才提供__reversed__()


3
列表似乎有更高效的实现方法,但元组却没有。 - wim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接