为什么在Python中颠倒和sorting不同的types?

reversed的types是“type”:

 >>> type(reversed) <class 'type'> 

sorted的types是“内build函数或方法”:

 >>> type(sorted) <class 'builtin_function_or_method'> 

但是,它们本质上看起来是一样的。 排除function上的明显差异(反转与sorting顺序),这种差异在实现中的原因是什么?

不同的是, reversed是一个迭代器(它也是懒惰评估), sorted是一个“热切”的function。

所有内置的迭代器(至less在python-3.x中)像mapzipfilterreversed ,…都是以类的forms实现的。 尽pipe热衷操作的内置函数函数 ,例如minmaxanyallsorted

 >>> a = [1,2,3,4] >>> r = reversed(a) <list_reverseiterator at 0x2187afa0240> 

你实际上需要“消耗”迭代器来获取值(例如list ):

 >>> list(r) [4, 3, 2, 1] 

另一方面,这种“消费”的部分是不需要像sorted function

 >>> s = sorted(a) [1, 2, 3, 4] 

在评论中被问及为什么这些被实现为类而不是function 。 这不是很容易回答,但我会尽我所能:

使用懒惰评估操作有一个巨大的好处:链接时它们的内存效率非常高。 他们不需要创build中间名单,除非他们明确“要求”。 这就是为什么mapzipfilter从热切操作函数(python-2.x)改为懒惰操作类(python-3.x)的原因。

通常Python中有两种方法来创build迭代器:

  • __iter__方法中return self
  • 生成器函数 – 包含yield函数

但是(至lessCPython)用C语言实现了所有的内build函数(和几个标准的库模块)。在C中创build迭代器类非常容易,但是我还没有find任何明智的方法来创build基于Python-C的生成器函数-API。 所以这些迭代器被实现为类(在CPython中)的原因可能只是方便或缺乏(快速或可实现的)select。

还有一个额外的原因是使用类而不是生成器:你可以为类实现特殊的方法,但是你不能在生成器函数上实现它们。 这听起来可能不会令人印象深刻,但它有一定的优势。 例如大多数迭代器可以使用__reduce____setstate__方法进行pickle (至less在Python-3.x中)。 这意味着您可以将它们存储在磁盘上,并允许复制它们。 由于Python-3.4一些迭代器也实现了__length_hint__ ,这使得使用list (和类似)的这些迭代器快得多。


请注意, reversed可以很容易地实现为工厂function(如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] 

尽pipe在iter情况下添加抽象层(工厂函数)是有意义的,因为返回的类取决于input参数的数量:

 >>> 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> 

reversedsorted什么区别?

有趣的是, reversed不是一个函数,而sorted是。

打开REPL会话并键入help(reversed)

 class reversed(object) | reversed(sequence) -> reverse iterator over values of the sequence | | Return a reverse iterator 

这确实是一个用来返回一个反向迭代器的类。

好的,如此reversed不是一个function。 但为什么不呢?

这有点难以回答。 一个解释是迭代器有懒惰的评价。 这需要某种容器在任何给定时间存储有关迭代器当前状态的信息。 这是最好的通过一个对象,因此,一个class