翻转元组和翻转列表会返回不同类型的对象:
>>> reversed((1,2))
<reversed at 0x7fffe802f748>
>>> reversed([1,2])
<list_reverseiterator at 0x7fffebdd4400>
它们具有相同的dir
属性。两种类型都不是彼此的子类。
为什么会这样?其中一种类型可以做什么另一种不能做?
翻转元组和翻转列表会返回不同类型的对象:
>>> reversed((1,2))
<reversed at 0x7fffe802f748>
>>> reversed([1,2])
<list_reverseiterator at 0x7fffebdd4400>
它们具有相同的dir
属性。两种类型都不是彼此的子类。
为什么会这样?其中一种类型可以做什么另一种不能做?
基本上,列表实现了__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
。
y
键将链接固定到特定提交。然后行号将永远不会偏离相关代码。我已经更新了你回答中的链接。 - wim
object.__reversed__(self)
如果存在,则被
reversed()
内置函数调用以实现反向迭代。它应该返回一个新的迭代器对象,该对象以相反的顺序迭代容器中的所有对象。如果未提供
__reversed__()
方法,则reversed()
内置函数将回退到使用序列协议(__len__()
和__getitem__()
)。支持序列协议的对象应仅在能够提供比reversed()
提供的更有效的实现时才提供__reversed__()
。