Python collections模块Counter类深入分析
2017-07-13 15:46
579 查看
Counter类介绍
Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。counter的初始化函数
Create a new, empty Counter object. And if given, count elements from an input iterable. Or, initialize the count from another mapping of elements to their counts.c = Counter() # a new, empty counter
c = Counter(‘gallahad’) # a new counter from an iterable
c = Counter({‘a’: 4, ‘b’: 2}) # a new counter from a mapping
c = Counter(a=4, b=2) # a new counter from keyword args
def __init__(*args, **kwds): if not args: raise TypeError("descriptor '__init__' of 'Counter' object needs an argument") self, *args = args if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) super(Counter, self).__init__() self.update(*args, **kwds)
这里可以看到,初始化函数接受args参数后,赋给了self,并在最后一步对参数进行了update,源码如下:
def update(*args, **kwds): if not args: raise TypeError("descriptor 'update' of 'Counter' object needs an argument") self, *args = args if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) iterable = args[0] if args else None if iterable is not None: if isinstance(iterable, Mapping): if self: self_get = self.get for elem, count in iterable.items(): self[elem] = count + self_get(elem, 0) else: super(Counter, self).update(iterable) # fast path when counter is empty else: _count_elements(self, iterable) if kwds: self.update(kwds)
对于上面的代码
片段1
iterable = args[0] if args else None
这里之所以可以用0去取参数,是因为函数入参时*将多个参数包装成了元组,由于这里只接受一个arg,因此可以直接arg[0]取值
片段2
if isinstance(iterable, Mapping):
dict在collections中也看作是一个Mapping
片段3
self_get = self.get
get方法如下所示,self_get = self.get只是把函数句柄交给了self_get(相当于匿名),get的实现如下
def get(self, key, default=None): return self[key] if key in self else default
注意这里传入了两个参数,对应的key和default
片段4
for elem, count in iterable.items():
因为是mapping,因此可以使用items方法(具体可见collections mapping,与dict很像)
片段5
_count_elements(self, iterable)
_count_elements方法如下
def _count_elements(mapping, iterable): 'Tally elements from the iterable.' mapping_get = mapping.get for elem in iterable: mapping[elem] = mapping_get(elem, 0) + 1
其中
mapping[elem] = mapping_get(elem, 0) + 1
直接迭代每个元素(不是mapping的情况,如果是list,可以直接在这里进行迭代),并调用get取出对应的元素,关于get,可以看到
这里是一个Mapping元素,在Mapping中没有找到对应的实现,但是在ChainMap中,可以看到下面的实现:
def get(self, key, default=None): return self[key] if key in self else default
其中,传入两个参数,分别对应着key,和default,其中self指的是_count_elements(mapping, iterable)中的mapping本身,因此,其实就是取出mapping中的elem元素,存在返回,不存在返回0。 注释6代码也就是在这个基础上+1
片段6
self.update(kwds)
如果存在多个参数,则会将后面的键值对包装为dict经嵌套调用后传给arg
结论
这个update函数也完美的说明了,Counter如何处理不同类型的初始化对象,如果传入字典(实际是Mapping)、列表与字符串(非Mapping,但是可迭代)有不同的处理方法,因此只要传入可迭代对象,理论上都是可以进行counter的,但是注意,这个可迭代对象应该是一维的,内部的每个元素应该应该为数字、字符串等简单类型的。如下面代码:
a = itertools.chain(*[[[1],[2],[3]],[[4],[5],[6]]])
输出结果:
Out[87]: <itertools.chain at 0x1e800cdd0b8> Counter(a) Traceback (most recent call last): File "C:\Users\chauncy\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 2885, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-88-acd8fd1b29c9>", line 1, in <module> Counter(a) File "C:\Users\chauncy\Anaconda3\lib\collections\__init__.py", line 530, in __init__ self.update(*args, **kwds) File "C:\Users\chauncy\Anaconda3\lib\collections\__init__.py", line 617, in update _count_elements(self, iterable) TypeError: unhashable type: 'list'
相关文章推荐
- Python中Collections模块的Counter容器类使用教程
- Python中Collections模块的Counter容器类使用教程
- Python中Collections模块的Counter容器类使用教程
- 简单掌握Python的Collections模块中counter结构的用法
- Python学习笔记(三十三)常用内置模块(2)collections_namedtuple_deque_defaultdict_OrderedDict_Counter
- 深入分析在Python模块顶层运行的代码引起的一个Bug
- Python collections中的Counter作用以及源码分析
- python3 Collections 模块的Counter类和namedtuple类
- 简单掌握Python的Collections模块中counter结构的用法
- 深入分析在Python模块顶层运行的代码引起的一个Bug
- python模块学习之数据结构--collections.counter
- Python中Collections模块的Counter容器类使用教程
- python Pexpect和Fabric模块对比分析
- python中文乱码问题深入分析
- 深入PHP购物车模块功能分析(函数讲解,附源码)
- python 中文乱码问题深入分析
- python collections模块
- python标准库logging模块代码分析
- 对Python中文分词模块结巴分词算法过程的理解和分析
- Python代码分析工具之dis模块