为什么在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中)像map
, zip
, filter
, reversed
,…都是以类的forms实现的。 尽pipe热衷操作的内置函数是函数 ,例如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
function :
>>> s = sorted(a) [1, 2, 3, 4]
在评论中被问及为什么这些被实现为类而不是function 。 这不是很容易回答,但我会尽我所能:
使用懒惰评估操作有一个巨大的好处:链接时它们的内存效率非常高。 他们不需要创build中间名单,除非他们明确“要求”。 这就是为什么map
, zip
和filter
从热切操作函数(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>
reversed
和sorted
什么区别?
有趣的是, reversed
不是一个函数,而sorted
是。
打开REPL会话并键入help(reversed)
:
class reversed(object) | reversed(sequence) -> reverse iterator over values of the sequence | | Return a reverse iterator
这确实是一个用来返回一个反向迭代器的类。
好的,如此
reversed
不是一个function。 但为什么不呢?
这有点难以回答。 一个解释是迭代器有懒惰的评价。 这需要某种容器在任何给定时间存储有关迭代器当前状态的信息。 这是最好的通过一个对象,因此,一个class
。