Python模块之collections
一、collections模块是干啥的?
collections模块在2.7的描述为High-performance container datatypes,高性能的容器性数据类型
collections模块在3.x的描述为Container datatypes,容器性数据类型
在这个模块为Python内置的容器性数据类型:dict, list, set, tuple提供了一些额外的其他容器性数据类型
namedtuple() |
factory function for creating tuple subclasses with named fields------ 工厂方法用来创建命名字段的tuple的子类 |
deque |
list-like container with fast appends and pops on either end--------- 双端队列,两边都可以追加和抛出 |
ChainMap |
dict-like class for creating a single view of multiple mappings------- 类字典类,可以创建多个mappings的单个视图 |
Counter |
dict subclass for counting hashable objects ------------------------------字典dict的子类,可以用来统计可哈希对象 |
OrderedDict |
dict subclass that remembers the order entries were added |
defaultdict |
dict subclass that calls a factory function to supply missing values |
UserDict |
wrapper around dictionary objects for easier dict subclassing |
UserList |
wrapper around list objects for easier list subclassing |
UserString |
wrapper around string objects for easier string subclassing |
二、ChainMap对象
1、啥是ChainMap,就是可以把多个mappings对象(字典)放一块,提供简单、可查询、可更新的视图(跟数据库的视图挺像的)。相比,大家再创建一个新的字典,然后把所有的字典都update到这个字典要快的多。
2、如果创建时,没有指定指定字典,默认内部有一个空字典。查找的时候,按照追加的字典的顺序依次查找,如果找到则返回(所以查的话,找到第一个带这个key的字典对应value值)。同理,新增,更新,删除仅仅操作第一个匹配到的
3、ChainMap支持所有的字典操作。额外还提供了字段属性maps,方法,如new_child(),还有一些方法属性parents等
4、代码学习时间:
from collections import ChainMap # 初始化定义两个字典 dict1 = {'a': 1, 'b': 2} dict2 = {'b': 3, 'c': 4} # 初始化一个ChainMap chain_dic = ChainMap(dict1,dict2) # 像普通字典一样使用 print(chain_dic['a']) print(chain_dic['b']) print(chain_dic['c']) print(list(chain_dic.keys())) print(list(chain_dic.values())) for k,v in chain_dic.items(): print(k,v) chain_dic['b'] = 7 print(chain_dic.maps) # 拿到chain_dic中的字典 print(chain_dic.maps) print(chain_dic.maps[0]) # 初始化chain_dict2 dic1 = { 'a' : 1, 'b' : 2 } dic2 = { 'b' : 3, 'c' : 4 } dic3 = { 'f' : 5 } # ChainMap的其他方法 chain = ChainMap(dic1, dic2) print(chain.maps) # [{'a': 1, 'b': 2}, {'c': 4, 'b': 3}] chain1 = chain.new_child(dic3) print(chain1) # ChainMap({'f': 5}, {'a': 1, 'b': 2}, {'c': 4, 'b': 3}) print(len(chain1)) # 4 print(dict(chain1)) # {'f': 5, 'a': 1, 'c': 4, 'b': 2} # ChainMap的反转 chain1.maps = reversed(chain1.maps) # 如何完成ChainMap的深层更新和删除,用类的继承来实现 class DeepChainMap(ChainMap): 'Variant of ChainMap that allows direct updates to inner scopes' def __setitem__(self, key, value): for mapping in self.maps: if key in mapping: mapping[key] = value return self.maps[0][key] = value def __delitem__(self, key): for mapping in self.maps: if key in mapping: del mapping[key] return raise KeyError(key)
三、Counter对象
1、是一个强大的、便捷的、快速的计数类
2、Counter是dict的子类,可以用来统计可哈希的对象。这个对象是不可排序的集合对象。元素通常以字典的键保存,出现的次数以字典的值保存。次数可以是任意整数包含0和负数。这和其他语言的bags或multisets很像。
3、Counter的实例化可以是可迭代对象,或者是其他mapping对象(字典)
from collections import Counter c = Counter() # 创建一个空的Counter c = Counter('gallahad') # 使用iterable创建一个Counter c = Counter({'red': 4, 'blue': 2}) # 使用mapping创建一个Counter c = Counter(cats=4, dogs=8) # 使用关键字参数创建一个Counter
c = Counter(dict(list_of_pairs)) # 使用tuple的list来创建
4、Counter实现了字典接口c['bacon'] ,不存在显示0,删除使用 del
5、版本3.X有一些新方法:
1. elements()方法: 将元素按照个数显示出来,会自动忽略计数为0和负的
>>> c = Counter(a=4, b=2, c=0, d=-2) >>> sorted(c.elements()) ['a', 'a', 'a', 'a', 'b', 'b']
2. most_common([n]),倒序显示最n多的部分,不指定n则显示所有
>>>Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)]
3.substract()方法,两个做差
>>> c = Counter(a=4, b=2, c=0, d=-2) >>> d = Counter(a=1, b=2, c=3, d=4) >>> c.subtract(d) >>> c Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
4.update
()方法,是将更新的和原来的相加,而不是替换
5.Counter的常用使用方法:
from collections import Counter c = Counter(a=10, b=2, c=11) sum(c.values()) # 所有的计数求和 23 # c.clear() # 清除所有的内容 list(c) # 显示所有的键 [a,b,c] set(c) # 转化成集合 {'a', 'c', 'b'} dict(c) # 转化成普通的字典 {'a': 10, 'c': 11, 'b': 2} c.items() # 转化成tuple的样子 (elem, cnt) # Counter(dict(list_of_pairs)) # 创建Counter的另一种方法 c.most_common()[:-2-1:-1] # 最少出现的n种元素 +c # 显示正个数的内容
6.还支持+、-、&、|方法
>>> c = Counter(a=3, b=1) >>> d = Counter(a=1, b=2) >>> c + d # add two counters together: c[x] + d[x] Counter({'a': 4, 'b': 3}) >>> c - d # subtract (keeping only positive counts) Counter({'a': 2}) >>> c & d # intersection: min(c[x], d[x]) Counter({'a': 1, 'b': 1}) >>> c | d # union: max(c[x], d[x]) Counter({'a': 3, 'b': 2})
四、deque对象(双端队列“double-ended queue)
1.deques是stacks和queues的组合。而且支持线程安全,内存高效追加和删除,而且双端的追加和删除,复杂度为O(1)
2.尽管list支持同样的操作。但是在左端追加和删除消耗 O(n)
3.deques可以设置maxlen,没有设置的话为None,就是无限长度。设置maxlen对于追踪事务,最新数据比较有用
4.代码时间:
from collections import deque deq = deque() # 增 deq.append(1) deq.appendleft(2) deq.extend([1,2,3,4]) deq.extendleft([1,2,3,4]) deq.insert(2,12) # 查 deq.index(2) # 复制 deq.copy() # 计数 deq.count(2) # 2 # print(deq.count(2)) # 删除 deq.pop() deq.popleft() deq.remove(12) # deq.clear() # 流转 print(deq) deq.rotate(-2) # 默认向右流转1 print(deq) # 还支持 iteration, pickling, len(d), reversed(d), copy.copy(d), copy.deepcopy(d),in ,切片等
5.deque的利用
1.1 获取文件的倒数几行
def tail(filename, n=10): 'Return the last n lines of a file' with open(filename) as f: return deque(f, n)
1.2 构造移动平均数
import itertools def moving_average(iterable, n=3): # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0 """ 构造移动平均线 :param iterable: 可迭代对象 :param n:几个数的平均值 :return:依次返回平均值 """ # http://en.wikipedia.org/wiki/Moving_average it = iter(iterable) d = deque(itertools.islice(it, n-1)) d.appendleft(0) s = sum(d) print(s) for elem in it: s += elem - d.popleft() d.append(elem) yield s / n for i in moving_average([40, 30, 50, 46, 39, 44],2): print(i)
1.3 删除第n个元素
def delete_nth(d, n): d.rotate(-n) d.popleft() d.rotate(n)
五、namedtuple()包含命名字段元祖工厂方法(命名元祖)
1、命名元祖给tuple的每个位置赋予含义,使其更具可读性。平时的tuples怎么使用,它也可以怎么使用。但是可以用名字直接访问而不是通过索引
2、namedtuple(typename,field_names,verbose=False,rename=False)实例化方法,typename返回一个typename类,可以用来实例化,field_names,可以用来指定对应的列:['x', 'y']、'x y'
or 'x, y'、可以使用任何Python的分隔符。rename=True,就是默认有的名字很奇葩,比如是Python默认的关键字,或者重复了是否自动帮你重命名,变成_1、_2
3、样例:
>>> # Basic example >>> Point = namedtuple('Point', ['x', 'y']) >>> p = Point(11, y=22) # instantiate with positional or keyword arguments >>> p[0] + p[1] # indexable like the plain tuple (11, 22) 33 >>> x, y = p # unpack like a regular tuple >>> x, y (11, 22) >>> p.x + p.y # fields also accessible by name 33 >>> p # readable __repr__ with a name=value style Point(x=11, y=22)
4、nametuples的应用:很方便处理csv或者sqlite返回的数据
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade') import csv for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))): print(emp.name, emp.title) import sqlite3 conn = sqlite3.connect('/companydata') cursor = conn.cursor() cursor.execute('SELECT name, age, title, department, paygrade FROM employees') for emp in map(EmployeeRecord._make, cursor.fetchall()): print(emp.name, emp.title)
5、nametuples的其他方法:
from collections import namedtuple Point = namedtuple('Point',['x','y']) p1 = Point(11,22) t2 = [22,33] # 创建Point的namedtuple p2 = Point._make(t2) # 生成一个OrderedDict() p2_ordered_dict = p2._asdict() # 更改namedtuple的值 p2._replace(x=33) # 查看namedtuple的字段 p2._fields
6.namedttuples的子类
from collections import namedtuple Point = namedtuple('Point',['x','y']) class Point(namedtuple('Point', ['x', 'y'])): __slots__ = () @property def hypot(self): return (self.x ** 2 + self.y ** 2) ** 0.5 def __str__(self): return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot) Point3D = namedtuple('Point3D', Point._fields + ('z',))
六、OrderedDict对象
1、就跟普通字典的使用是一样的,但是注意OrderedDict的键值对是有序的,首先添加的首先返回
2、一些额外的方法:
popitem() 抛出一个(key,value)对
move_to_end(key,last = True) 将某个键移到两端 ,last = True移到末尾, last = Flase,移到开始
3、OrderedDict使用样例
>>> # regular unsorted dictionary >>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2} >>> # dictionary sorted by key >>> OrderedDict(sorted(d.items(), key=lambda t: t[0])) OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)]) >>> # dictionary sorted by value >>> OrderedDict(sorted(d.items(), key=lambda t: t[1])) OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)]) >>> # dictionary sorted by length of the key string >>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0]))) OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
七、UserString、UserDict、UserList
主要用来用于自定义继承string、dict、list