import collections
'''
collections.ChainMap(dict1, dict2,...)
将多个字典链在一起,并不是将多个字典真正的合并。如果key重复,就以位置最靠前的为准
'''
person1 = {'name1': '张三', 'age': 18, 'height': 1.8}
person2 = {'name2': '李四', 'age2': 19, 'height': 1.7}
person3 = {'name3': '王五', 'age': 20, 'height3': 1.75}
res = collections.ChainMap(person1, person2, person3)
print(res)
# ChainMap({'name1': '张三', 'age': 18, 'height': 1.8}, {'name2': '李四', 'age2': 19, 'height': 1.7}, {'name3': '王五', 'age': 20, 'height3': 1.75})
print(res['name1']) # 张三
print(res['name2']) # 李四
print(res['name3']) # 王五
print(res['age']) # 18
print(res['height']) # 1.8
'''
collections.Counter(iterable)
用来统计容器里面元素出现的次数,返回值相当于一个字典
对于 Counter 对象还有一些很常用的操作,比如把 Counter 对象转换成 set(集合)、list(列表)、dict(字典)等,
程序还可对 Counter 执行加、减、交、并运算,对 Counter 进行求正、求负运算等。对 Counter 执行各种运算的含义如下:
加:将两个 Counter 对象中各 key 出现的次数相加,且只保留出现次数为正的元素。
减:将两个 Counter 对象中各 key 出现的次数相喊,且只保留出现次数为正的元素。
交:取两个 Counter 对象中都出现的 key 且各 key 对应的次数的最小数。
并:取两个 Counter 对象中各 key 对应的出现次数的最大数。
求正:只保留 Counter 对象中出现次数为 0 或正数的 key-value 对。
求负:只保留 Counter 对象中出现次数为负数的 key-value 对,并将出现次数改为正数。
'''
c = collections.Counter('hfsefseh')
print(c)
# Counter({'h': 2, 'f': 2, 's': 2, 'e': 2})
print(c.most_common(2)) # 出现频率最高的前两位
# [('h', 2), ('f', 2)]
print(list(c.elements())) # 查看出现在统计表中的元素的排序
c1 = collections.Counter([1,2,3,4,3,1,2])
print(c1) # Counter({1: 2, 2: 2, 3: 2, 4: 1})
c2 = collections.Counter({'python':5, 'go':4})
print(c2) # Counter({'python': 5, 'go': 4})
c3 = collections.Counter(python=5, go=4)
print(c3) # Counter({'python': 5, 'go': 4})
c3.subtract(['python', 'python', 'go']) # 将Counter c3依次减去列表里面出现的次数
print(c3) # Counter({'python': 3, 'go': 3})
'''
collections.defaultdict()
defaultdict 是 dict 的子类,因此 defaultdict 也可被当成 dict 来使用,dict 支持的功能,defaultdict 基本都支持。
但它与 dict 最大的区别在于,如果程序试图根据不存在的 key 采访问 dict 中对应的 value,则会引发 KeyError 异常;
而 defaultdict 则可以提供一个 default_factory 属性,该属性所指定的函数负责为不存在的 key 来生成 value。
'''
my_defaultdict = collections.defaultdict(int)
print(my_defaultdict['a']) # 我们并没有给my_defaultdict设定'a'这个键,但是我们取访问并没有引发KeyError异常
s = [('Python', 1), ('Swift', 2), ('Python', 3), ('Swift', 4), ('Python', 9)]
d = {}
for k, v in s:
# setdefault()方法用于获取指定key对应的value.
# 如果该key不存在,则先将该key对应的value设置为默认值:[]
d.setdefault(k, []).append(v)
print(d.items())
'''
collections.namedtuple()
namedtuple() 是一个工厂函数,使用该函数可以创建一个 tuple 类的子类,该子类可以为 tuple 的每个元素都指定宇段名,
这样程序就可以根据字段名来访问 namedtuple 的各元素了。当然,如果有需要,程序依然可以根据索引来访问namedtuple 的各元素。
namedtuple 是轻量级的,性能很好,其并不比普通 tuple 需要更多的内存
namedtuple(typename, field_names, *, verbose=False, rename=False, module=None)
typename:该参数指定所创建的 tuple 子类的类名,相当于用户定义了一个新类。
field_names:该参数是一个字符串序列,如 ['x','y']。此外,field_names 也可直接使用单个字符串代表所有字段名,多个字段名用空格、逗号隔开,
如 'x y' 或 'x,y'。任何有效的 Python 标识符都可作为字段名(不能以下画线开头)。有效的标识符可由字母、数字、下画线组成,但不能以数字、
下面线开头,也不能是关键字(如 return、global、pass、raise 等)。
rename:如果将该参数设为 True,那么无效的字段名将会被自动替换为位置名。例如指定 ['abc','def','ghi','abc'],
它将会被替换为 ['abc', '_1','ghi','_3'],这是因为 def 字段名是关键字,而 abc 字段名重复了。
verbose:如果该参数被设为 True,那么当该子类被创建之后,该类定义就会被立即打印出来。
module:如果设置了该参数,那么该类将位于该模块下,因此该自定义类的 __module__ 属性将被设为该参数值
'''
Point = collections.namedtuple('Point', 'x y')
p1 = Point(10, 20)
print(p1.x) # 命名元组可以以属性的方式访问
print(p1.y)
print(p1[0]) # 命名元组也可以以下标的形式访问
print(p1[1])
'''
命名元组的其他方法:
_make(iterable):类方法。该方法用于根据序列或可迭代对象创建命名元组对象。
_asdict():将当前命名元组对象转换为 OrderedDict 字典。
_replace(**kwargs):替换命名元组中一个或多个字段的值。
_source:该属性返回定义该命名元组的源代码。
_fields:该属性返回该命名元组中所有字段名组成的元组。
'''
my_data = ['name', 'age']
p2 = Point._make(my_data)
print(p2.x) # name
print(p2.y) # age
print(p2._asdict()) # OrderedDict([('x', 'name'), ('y', 'age')])
print(p2._replace(y='height')) # Point(x='name', y='height')
print(p2._fields) # ('x', 'y')
'''
collections.OrderDict
OrderedDict 也是 dict 的子类,其最大特征是,它可以“维护”添加 key-value 对的顺序。简单来说,
就是先添加的 key-value 对排在前面,后添加的 key-value 对排在后面。
'''
od = collections.OrderedDict(a=1, b=2, c=3)
print(od) # OrderedDict([('a', 1), ('b', 2), ('c', 3)])
od['name'] = '张三'
od['age'] = 16
print(od) # OrderedDict([('a', 1), ('b', 2), ('c', 3), ('name', '张三'), ('age', 16)])
'''
popitem(last=True):默认弹出并返回最右边(最后加入)的 key-value 对;如果将 last 参数设为 False,
则弹出并返回最左边(最先加入)的 key-value 对。
move_to_end(key, last=True):默认将指定的 key-value 对移动到最右边(最后加入);如果将 last 改为 False,
则将指定的 key-value 对移动到最左边(最先加入)。
'''
d = collections.OrderedDict().fromkeys('abcdef')
print(d)
d.move_to_end('b', last=True)
print(d)
d.popitem(last=True)
print(d)
'''
collections.deque---双端队列
append 和 appendleft:在 deque 的右边或左边添加元素,也就是默认在队列尾添加元素。
pop 和 popleft:在 deque 的右边或左边弹出元素,也就是默认在队列尾弹出元素。
extend 和 extendleft:在 deque 的右边或左边添加多个元素,也就是默认在队列尾添加多个元素。
deque 中的 clear() 方法用于清空队列:insert() 方法则是线性表的方法,用于在指定位置插入元素。
'''
'''
将deque当做栈使用,只能在一端添加或删除元素
栈的特点的是先进先后出
'''
stack = collections.deque(['张三', '李四', '王五'])
print(stack) # deque(['张三', '李四', '王五'])
stack.append('赵六')
print(stack) # deque(['张三', '李四', '王五', '赵六'])
res = stack.pop()
print(res) # 赵六
print(stack) # deque(['张三', '李四', '王五'])
'''
将deque当做队列使用,只能在一端添加元素,在另一端删除元素
队列的特点是先进先出
'''
q = collections.deque(['张三', '李四', '王五'])
print(q) # deque(['张三', '李四', '王五'])
q.appendleft('赵六')
print(q) # deque(['赵六', '张三', '李四', '王五'])
res = q.pop()
print(res) # 王五
print(q) # deque(['赵六', '张三', '李四'])
if __name__ == '__main__':
pass