Counter
的 elements()
方法返回一个迭代器。元素被重复了多少次,在该迭代器中就包含多少个该元素。所有元素按照字母序排序,个数小于1的元素不被包含。
举例:
1 | >>> c = Counter('ABCABC') |
源码如下:
1 | def elements(self): |
好!!!精!!!简!!!
从里往外看这行代码吧:
1 | _starmap(_repeat, self.iteritems()) |
_starmap
是 itertools
模块中的一个实现了 __iter__
方法的类,构造器接收两个参数:一个函数(function)和一个序列(sequence),作用是创建一个迭代器,生成值function(*item),其中item来自sequence,只有当sequence生成的项适用于这种调用函数的方式时,此函数才有效。
itertools.starmap(function, iterable)
等价于:
1 | def starmap(function, iterable): |
举例:
1 | from itertools import starmap |
所以 _starmap(_repeat, self.iteritems())
等价于下边的代码:
1 | for item in self.iteritems(): |
也就是返回一个迭代器,迭代器的每一项是使用item
解包作为参数来调用 _repeat
的结果。
下边再来看_repeat
:itertools.repeat(object[, times])
,同样也是实现了__iter__
方法的类,作用是创建一个迭代器,重复生成object,times(如果已提供)指定重复计数,如果未提供times,将无止尽返回该对象。
等价于:
1 | def repeat(object, times=None): |
举例:
1 | from itertools import * |
repeat
很容易理解就不用解释了。
下边我们返回去看_starmap(_repeat, self.iteritems())
, 这些完这些,得到的结果是一个迭代器里边每一项依然是个迭代器,每个内层迭代器迭代出的结果是重复生成的项。
可以想象成这样:
1 | >>> _starmap(_repeat, [{'A': 2, 'B': 3, 'C': 4}]) |
再来看一下chain
:itertools.chain(*iterables)
, 将多个迭代器作为参数, 但只返回单个迭代器, 它产生所有参数迭代器的内容, 就好像他们是来自于一个单一的序列。
等价于:
1 | def chain(*iterables): |
举例:
1 | for i in chain([1, 2, 3], ['a', 'b', 'c']): |
chain
的 类函数 from_iterable
可以理解成接收一个参数,然后将这个参数解包后调用构造器。
以上例子也可以写成:
1 | for i in chain.from_iterable([[1, 2, 3], ['a', 'b', 'c']]): |
所以,用 chain
来合并 _starmap(_repeat, self.iteritems())
得到的嵌套迭代器后得到的就是我们需要的结果了!
最后再次感叹下Python代码的精简!
更正前几篇中的出现过的一个错误:
字典调用 iteritems
方法得到的并不是一个列表,而是一个迭代器。
之前把 iteritems
一直当成 items
了。
1 | >>> x = {'title':'python web site','url':'www.iplaypython.com'} |