【问题标题】:What's the difference between a reversed tuple and a reversed list?反向元组和反向列表有什么区别?
【发布时间】:2017-03-03 02:59:48
【问题描述】:

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

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

他们有相同的dir。两种类型都不是另一种类型的子类。

这是为什么呢?一个人能做什么,另一个人不能?

【问题讨论】:

  • 除非您使用可以在 listreverseiterator 上调用 len 的较旧版本的 python,否则栏性能似乎没有差异。 bugs.python.org/issue3689.

标签: python python-internals reverse-iterator


【解决方案1】:

基本上,列表实现__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

【讨论】:

  • 一个人能做什么而另一个人不能?
  • Github pro-tip:如果你像这样链接到 blob/master 中的行号,一旦文件被修改,链接就会失效。相反,选择您想要的行,然后按y 键,将链接固定到特定提交。那么行号将永远不会偏离相关代码。我已经更新了您答案中的链接。
  • @wim 谢谢。直到关于'y'。我知道链接失效,但总是手动找到提交。
  • 是否有任何理由使用不同的迭代器,因为list 可能是可变的?
【解决方案2】:

根据Python的documentation

object.__reversed__(self)

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

如果没有提供__reversed__() 方法,则reversed() 内置将回退到使用序列协议(__len__()__getitem__())。支持序列协议的对象 如果他们可以提供__reversed__() 比提供的更有效的实现 reversed().

【讨论】:

  • list 有更高效的实现似乎很奇怪,但 tuple 没有。
猜你喜欢
  • 2018-09-30
  • 2020-04-29
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-31
  • 2016-02-23
相关资源
最近更新 更多