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)
ChainMap

三、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)
tail(filename,n=10)

   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)
删除第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

posted @ 2017-06-06 07:02  skiler  阅读(282)  评论(0编辑  收藏  举报