reversed
的类型是"输入":
>>> type(reversed)
<class 'type'>
sorted
&#39;类型是&#34;内置函数或方法&#34;:
>>> type(sorted)
<class 'builtin_function_or_method'>
然而,它们在性质上看起来是一样的。排除功能上的明显差异(逆转与排序序列),实现这种差异的原因是什么?
答案 0 :(得分:51)
不同之处在于reversed
是一个迭代器(它也是懒惰的评估),而sorted
是一个可以正常工作的函数。#/ p>
所有内置迭代器(至少在python-3.x中),如map
,zip
,filter
,reversed
,...实现为<强>类即可。虽然热切操作的内置插件是功能,例如min
,max
,any
,all
和sorted
。
>>> a = [1,2,3,4]
>>> r = reversed(a)
<list_reverseiterator at 0x2187afa0240>
你实际上需要&#34;消费&#34;获取值的迭代器(例如list
):
>>> list(r)
[4, 3, 2, 1]
另一方面,这&#34;消费&#34; 功能需要部分,例如sorted
:
>>> s = sorted(a)
[1, 2, 3, 4]
在评论中,有人问为什么将这些实现为类而不是函数。这并不容易回答,但我会尽我所能:
使用延迟评估操作有一个巨大的好处:链接时它们的内存效率非常高。他们不需要创建中间列表,除非他们明确地要求&#34;。这就是为什么map
,zip
和filter
从急切操作函数(python-2.x)更改为延迟操作类(python-3.x)的原因。< / p>
通常,Python有两种方法来创建迭代器:
return self
方法__iter__
的课程
yield
然而(至少CPython)在C中实现了所有内置函数(和几个标准库模块)。在C中创建迭代器类非常容易,但我还没有找到任何合理的方法基于Python-C-API创建生成器函数。因此,将这些迭代器实现为类(在CPython中)的原因可能只是方便或缺少(快速或可实现的)替代方案。
使用类而不是生成器还有另外一个原因:您可以为类实现特殊方法,但不能在生成器函数上实现它们。这听起来可能并不令人印象深刻,但它有一定的优例如,大多数迭代器可以使用pickled和__reduce__
方法__setstate__
(至少在Python-3.x上)。这意味着您可以将它们存储在磁盘上,并允许复制它们。从Python-3.4开始,一些迭代器也实现了__length_hint__
,这使得使用list
(和类似)的迭代器的速度要快得多。
请注意,reversed
可以轻松实现为工厂功能(如iter
),但不像iter
,它可以返回两个唯一的类,{{ 1}}只能返回一个唯一的类。
为了说明可能的(和唯一的)类,您必须考虑一个没有__iter__
且没有__reversed__
方法但可迭代和反向迭代的类(通过实现__getitem__
和__len__
):
reversed
虽然在class A(object):
def __init__(self, vals):
self.vals = vals
def __len__(self):
return len(self.vals)
def __getitem__(self, idx):
return self.vals[idx]
的情况下添加抽象层(工厂函数)是有意义的 - 因为返回的类取决于输入参数的数量:
iter
这种推理并不适用于>>> iter(A([1,2,3]))
<iterator at 0x2187afaed68>
>>> iter(min, 0) # actually this is a useless example, just here to see what it returns
<callable_iterator at 0x1333879bdd8>
:
reversed
答案 1 :(得分:4)
reversed
和sorted
之间有什么区别?
有趣的是,reversed
不是函数,而sorted
是。
打开REPL会话并输入help(reversed)
:
class reversed(object)
| reversed(sequence) -> reverse iterator over values of the sequence
|
| Return a reverse iterator
它确实是一个用于返回反向迭代器的类。
好的,
reversed
不是函数。但为什么不呢?
这有点难以回答。一种解释是迭代器具有惰性评估。这需要某种容器来存储有关任何给定时间迭代器当前状态的信息。这最好通过一个对象完成,因此,class
。