Python中的高性能容器--collections

集合模块

  相对于 Python 中内置的称为链表、集合、字典和元组的默认容器类型来说,集合模块( collection module )提供了高性能的备选方案( alternative )。

  简单地看看集合模块中如下的容器类型:

    1 ) deque :一个链表容器的备选方案,支持在队列两端快速插入和弹出( pop )。

    2 ) defaultdict : dict 的子类,它为类型提供了工厂函数,用于提供缺省值。

    3 ) orderedDict : dict 的子类,它记录了关键字插入的顺序。

    4 ) Counter : dict 子类,用于保存可哈希类型的计数和统计信息。

    5 ) ChainMap :带有一个类似字典接口的类,用于持续跟踪多重映射。

    6 ) namedtuple :用于创建类似元组的类的类型,带有命名字段。

  1 . deque

  一个双端队列( double ended queue )像一个链表,但和链表不同,它支持近乎常量时间( O ( 1) )的从队列两端进行的增加和弹出操作,而链表对于在左端进行的弹出和插入操作,有一个 0 ( n )数量级的时间成本。

  双端队列也支持一些操作,比如旋动( rotation ) ,用于将列表中 k 个元素从表尾移动到表头,或者反过来,它们的平均性能为 O ( k )。这通常比链表中类似的操作稍微快一点,链表涉及切割( slicing )和追加( appending )操作:

  

# 定义一个双端队列
import collections

dq = collections.deque()

# append往右边添加一个元素
dq.append(1)
dq.append(2)
print(dq)  # deque([1, 2])

# appendleft往左边添加一个元素
dq.appendleft(3)
dq.appendleft(4)
print(dq)  # deque([4, 3, 1, 2])

# clear 清空队列
dq.clear()
print(dq)  # deque([])

# copy浅拷贝
dq.append(1)
dq2 = dq.copy()
print(id(dq))  # 4398288576
print(id(dq2))  # 4398288240

# count 返回指定元素的出现次数
dq3 = collections.deque()
dq3.append(1)
dq3.append(1)
print(dq3.count(1))  # 2

# extend 从队列右端添加多个元素
dq4 = collections.deque()
dq4.append(1)
dq4.extend([2, 3, 4])
print(dq4)  # deque([1, 2, 3, 4])

# extendleft 从队列左端添加多个元素  注意添加顺序
dq4.extendleft([5, 6, 7, 8])
print(dq4)  # deque([8, 7, 6, 5, 1, 2, 3, 4])

# index 查找某个元素的索引位置,如果查无结果  会报异常 ValueError: xxx is not in deque
print(dq4.index(5))  # 3
print(dq4.index(2, 3, 7))  # 后面的两个参数可用于指定查找区间

# insert 在队列指定位置插入元素
dq4.insert(2, "c")
print(dq4)  # deque([8, 7, ‘c‘, 6, 5, 1, 2, 3, 4])

# pop 返回队列最右边的元素,并将其在队列中删除
print(dq4)  # deque([8, 7, ‘c‘, 6, 5, 1, 2, 3, 4])
x = dq4.pop()
print(x)  # 4
print(dq4)  # deque([8, 7, ‘c‘, 6, 5, 1, 2, 3])

# popleft 返回最左边的元素,并将其在队列中删除
print(dq4)  # deque([8, 7, ‘c‘, 6, 5, 1, 2, 3])
y = dq4.popleft()
print(y)  # 8
print(dq4)  # deque([7, ‘c‘, 6, 5, 1, 2, 3])

# remove 删除指定元素, 只删除一个值,从左向右查找
dq5 = collections.deque([1, 2, 3, 4, 5, 2])
print(dq5)  # deque([1, 2, 3, 4, 5, 2])
dq5.remove(2)
print(dq5)  # deque([1, 3, 4, 5, 2])
dq5.remove(2)
print(dq5)  # deque([1, 3, 4, 5])

# reverse 反转队列
print(dq5)  # deque([1, 3, 4, 5])
dq5.reverse()
print(dq5)  # deque([5, 4, 3, 1])

# rotate 将右边元素放置到队列左边
dq5.rotate(2)  # 可指定次数
print(dq5)  # deque([3, 1, 5, 4])

  2 . defaultdict

  默认dict是dict子类, 它使用类型工厂提供对于字典关键字的默认值。

  在Python中,当在一个列表数据项上循环,并试着增加一个字典计数值的时候,我们会遇到一个常见问题,即有可能没有对应数据项的任何已存在的条目

  比如,对一个单词在一段文本中的出现次数进行计数:

counts = {}

for word in text.split():
    word = word.lower().strip()
    try:
        counts[word] += 1
    except KeyError:
        counts[word] = 1

  再比如,试着对所有的字符串分组,相同长度的字符串放到一个字典中:

cities = [‘Jakarta‘, ‘Delhi‘, ‘Newyork‘, ‘Bonn‘, ‘Kolkata‘, ‘Bangalore‘, ‘Seoul‘]

cities_len = {}
for city in cities:
    clen = len(city)
    # First create entry
    if clen not in cities_len:
        cities_len[clen] = []
    cities_len[clen].append(city)

  一个defaultdict容器优雅地解决了这个问题,它通过定义一个类型工厂为任务没在字典中出现的关键字提供默认参数值。 默认工厂类型支持任意的默认类型, 而且默认值设为None。

  对于每种类型,它的空值是默认值,即:

  int -> 0

  [] -> list

  ‘‘ ->strings

  {} ->dict

  单词计数代码可以按照如下方式重写:

counts = collections.defaultdict(int)

for word in text.split():
    word = word.split()
    # Value is set to 0 and incremented by 1 in one go
    counts[word] += 1

  类似地,根据字符串长度分组它们的代码如下:  

cities = [‘Jakarta‘, ‘Delhi‘, ‘Newyork‘, ‘Bonn‘, ‘Kolkata‘, ‘Bangalore‘, ‘Seoul‘]

cities_len = collections.defaultdict(list)

for city in cities:
    # Empty list is created as value and appended to in one go
    cities_len[len(city)].append(city)

  3 . OrderedDict

  OrderedDict 是一个dict子类, 它记录了条目插入的顺序,它有点像一个字典和链表的结合体,它表现得像一个映射类型,但是在记录插入顺序,甚至支持诸如用于删除头尾条目的popitem方法上,也有类似链表的行为

cities = [‘Jakarta‘, ‘Delhi‘, ‘Newyork‘, ‘Bonn‘, ‘Kolkata‘, ‘Bangalore‘, ‘Seoul‘]
cities_dict= collections.OrderedDict.fromkeys(cities)
print(cities_dict)  # OrderedDict([(‘Jakarta‘, None), (‘Delhi‘, None), (‘Newyork‘, None), (‘Bonn‘, None), (‘Kolkata‘, None), (‘Bangalore‘, None), (‘Seoul‘, None)])
print(cities_dict.popitem())  # (‘Seoul‘, None)
print(cities_dict.popitem(last=False))  #(‘Jakarta‘, None)

  比较和对照字典是如何改变顺序的,而OrderedDict容器是如何保持原有顺序的。

  这里给出了一些使用OrderedDict容器的做法。

  1)不丢失顺序地从一个容器中删除重复元素。

cities = [‘Jakarta‘, ‘Delhi‘, ‘Newyork‘, ‘Bonn‘, ‘Kolkata‘, ‘Bangalore‘, ‘Bonn‘, ‘Seoul‘, ‘Delhi‘, ‘Jakarta‘, ‘Mumbai‘]

cities_odict = collections.OrderedDict.fromkeys(cities)
print(cities_odict.keys())

  2) 实现一个最近最少使用(LRU)的缓存字典。

  一个LRU缓存优先考虑最近被使用(或被访问)的条目,删除那些最少被使用的条目。这是一个常见的缓存算法,用在诸如Squid的HTTP缓存服务器中,也用在其他一些情况中,即需要维护一个被限制了大小的容器,这个容器优先保存最近被访问的条目。

  这里使用了OrderedDict的操作,即当删除了一个存在的关键字,然后再重新添加时,它被添加到了末尾(右端):

  

class LRU(collections.OrderedDict):
    """ Least recently used cache dictionary"""

    def __init__(self, size=10):
        self.size = size

    def set(self, key):
        # if key is there delete and reinsert so
        # it moves to end
        if key in self:
            del self[key]

        self[key] = 1
        if len(self) > self.size:
            # pop from left
            self.popitem(lastp=False)
lru = LRU(5)lru.set("bangalore")lru.set("chennai")lru.set("mumbai")lru.set("bangalore")lru.set("kolkata")lru.set("delhi")lru.set("chennai")lru.set("kochi")
print(lru) # LRU([(‘bangalore‘, 1), (‘kolkata‘, 1), (‘delhi‘, 1), (‘chennai‘, 1), (‘kochi‘, 1)])

  因为关键字mumbai第一个被设置,之后没有再被设置过,所以它变成了最左边的一个,然后被删除了。

  注意:要删除的下一个关键字是 bangalore, 接着是 chennai,这是因为chennai在bangalore设置之后被多设置了一次

  4. Counter

  5. ChainMap

  6. Namedtuple

  

原文地址:https://www.cnblogs.com/82nlf-xlqb/p/11830637.html

时间: 2024-10-12 23:07:07

Python中的高性能容器--collections的相关文章

Python中5种容器数据类型之性质对照表

以下是作者总结的Python五大容器类数据类型的性质对照表,供大家参考记忆. 原文地址:https://www.cnblogs.com/wangliman/p/9697349.html

Python中的高级数据结构(转)

add by zhj: Python中的高级数据结构 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据 结构,分别是List.Tuple.Dictionary以及Set.大部分的应用程序不需要其他类型的数据结构,但若是真需要也有很多高级数据结构可供 选择,例如Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint.本文将介绍这些数据结构的用法,看 看它

Python中的高级数据结构详解

这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考下 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据结构,分别是List.Tuple.Dictionary以及Set.大部分的应用程序不需要其他类型的数据结构,但若是真需要也有很多高级数据结构可供选择

python 中的queue, deque

创建双向队列 import collections d = collections.deque() append(往右边添加一个元素) import collections d = collections.deque() d.append(1) d.append(2) print(d) #输出:deque([1, 2]) appendleft(往左边添加一个元素) import collections d = collections.deque() d.append(1) d.appendlef

Python中socket编程

1.Socket介绍: Python中提供socket.py标准库,非常底层的接口库. Socket是一种通用的网络编程接口,和网络层次没有一一对应关系. 跨操作系统的.紧密结合tcp和udp来使用的. 接口简单,但是背后的原理不简单,ip加tcp,通过插两端.通过socket通道:连接程序. 建立关联. apc库. 加端口是因为应用程序太多了.绑定ip地址,作为假端口. 端口是由谁管理的 一般都是tcp和udp编程.Socket基本的,chatserver. 协议族:AF 表示address

python中的关键字---7(re/序列化/Counter模块)

import re  正则 正则表达式 # 元字符 # \w 数字字母下划线 # \W 非数字字母下划线 # \d 数字 # \D 非数字 # \s 空白符(空格\制表符\换行符) # \S 非空白符 # \t 制表符 # \n 换行符 # \b 单词的边界 # . 除了换行符以外的所有 # ^ 开始 # $ 结尾 # [..] 字符组 # [^..] 非字符组 # | 或(包含关系中,长的在前面) # () 分组(在或的两端,在添加量词的时候,findall的时候优先要显示的) # (123\

python中的各个模块

collection模块:python中的扩展数据模块#namedtuple: 生成可以使用名字来访问元素内容的tuple'''from collections import namedtuplePoint=namedtuple('point',['x','y']) #必须起名字 pointp=Point(1,2)print(p.x) #表示坐标中的x点print(p.y)print(p) #point(x=1, y=2) 表示坐标'''#deque 双端队列,快速的从另外一侧追加和推出对象 适

Python中的垃圾回收机制

当我们声明一个对象的时候,例如str="abcdef",当我们不再使用str这个对象的时候,这个对象就是一个脏对象,垃圾对象,但是它还在占着内存,毕竟我们的电脑内存有限,所以应该有一个机制来回收它以及类似的对象.现在的高级语言如java,c#等,都采用了垃圾收集机制,而不再是c,c++里用户自己管理维护内存的方式.自己管理内存极其自由,可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患. 对于一个字符串.列表.类甚至数值都是对象,且定位简单易用的语言,自然不会

Python中常见的数据类型总结(三)

4.通用的序列操作方法 (1)索引 在访问序列元素中用到,如下: >>> L = ['a','b','c']>>> L[1]'b'>>> T = (1,2,3)>>> T[0]1 >>> str = "Python">>> str[4]'o' (2)分片 分片用来访问一定范围内的元素,分片通常通过冒号相隔的两个索引来实现,常见的有如下几种: >>> a = li