区别在于reversed 是一个迭代器(它也是惰性求值),而sorted 是一个“热切”工作的函数。
像map、zip、filter、reversed 等所有内置迭代器(至少在 python-3.x 中)都实现为 类。虽然急切操作的内置函数是 functions,例如min、max、any、all 和 sorted。
>>> a = [1,2,3,4]
>>> r = reversed(a)
<list_reverseiterator at 0x2187afa0240>
您实际上需要“使用”迭代器来获取值(例如list):
>>> list(r)
[4, 3, 2, 1]
另一方面,像sorted这样的函数不需要这个“消耗”部分:
>>> s = sorted(a)
[1, 2, 3, 4]
在 cmets 中,有人问为什么将这些实现为类而不是函数。这不是很容易回答,但我会尽力而为:
使用惰性求值操作有一个巨大的好处:它们在链接时非常节省内存。他们不需要创建中间列表,除非他们被明确“请求”。这就是为什么 map、zip 和 filter 从急切操作函数 (python-2.x) 更改为惰性操作类 (python-3.x) 的原因。
Python中创建迭代器一般有两种方式:
-
return self 在其__iter__ 方法中的类
- 生成器函数 - 包含
yield 的函数
但是(至少是 CPython)在 C 中实现了它们的所有内置函数(和几个标准库模块)。在 C 中创建迭代器类非常容易,但我还没有找到任何明智的方法来创建基于Python-C-API。因此,这些迭代器被实现为类(在 CPython 中)的原因可能只是方便或缺乏(快速或可实现的)替代方案。
使用类而不是生成器还有一个原因:您可以为类实现特殊方法,但不能在生成器函数上实现它们。这听起来可能并不令人印象深刻,但它具有明显的优势。例如,大多数迭代器可以是 pickled(至少在 Python-3.x 上)使用 __reduce__ 和 __setstate__ 方法。这意味着您可以将它们存储在磁盘上,并允许复制它们。由于 Python-3.4 一些迭代器也实现了__length_hint__,这使得使用list(和类似的)的迭代器更快。
注意reversed 可以很容易地实现为工厂函数(如iter),但与iter 不同,它可以返回两个唯一 类,reversed 只能返回一个独特的类。
为了说明可能的(和唯一的)类,您必须考虑一个没有__iter__ 和__reversed__ 方法但可迭代和反向迭代的类(通过实现__getitem__ 和__len__):
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:
>>> reversed(A([1,2,3]))
<reversed at 0x2187afaec50>