RingBuffer,或者说Circular Buffer,是一个长度固定的缓冲区,当从一端插入元素超过指定的最大长度时,缓冲区另一端的元素会溢出。当用户仅对近期一定长度的历史记录感兴趣时,这种数据结构就特别有用。

* 缓冲区的长度固定

* 先进先出

* 当往缓冲区中增加或者删除元素时,其它元素的位置保持不变。

本文介绍了三种实现方法及各自的特点。

# collections.dequeue实现

RingBuffer的一个直观实现是使用Pyhton collections的dequeue(发音deck):

```Python

import collections

import time

d = collections.deque(maxlen=1000)

tm1 = time.time()

for i in range(int(1e6)):

d.append(i)

print(list(d)[:10])

d.clear()

tm2 = time.time()

print("{:.2f}seconds".format(tm2 - tm1))

执行结果如下:

[999000, 999001, 999002, 999003, 999004, 999005, 999006, 999007, 999008, 999009]

0.20seconds

支持的操作有pop, append;以及从左端操作的popleft, appendleft。但没有缓冲区需要的read操作。缓冲区read操作包括两个动作,一是从缓冲区中读取数据;二是在读取后清除掉数据。我们可以通过list(d:dequeue)和clear的组合来实现这一功能。

# 一个有趣的自定义实现

David Ascher在[这篇文章](#Implementing a Ring Buffer [Book])里给出了一个自定义的实现:

```python

class RingBuffer:

""" class that implements a not-yet-full buffer """

def __init__(self,size_max):

self.max = size_max

self.data = []

class __Full:

""" class that implements a full buffer """

def append(self, x):

""" Append an element overwriting the oldest one. """

self.data[self.cur] = x

self.cur = (self.cur+1) % self.max

def get(self):

""" return list of elements in correct order """

ret = self.data[self.cur:]+self.data[:self.cur]

self.data.clear()

return ret

def append(self,x):

"""append an element at the end of the buffer"""

self.data.append(x)

if len(self.data) == self.max: #line 21

self.cur = 0

# Permanently change self's class from non-full to full

self.__class__ = self.__Full

def get(self):

""" Return a list of elements from the oldest to the newest. """

return self.data

x = RingBuffer(1000)

import time

tm1 = time.time()

for i in range(int(1e6)):

x.append(i)

print(x.get()[:10])

tm2 = time.time()

print("{:.2f}seconds".format(tm2 - tm1))

执行结果如下:

[999000, 999001, 999002, 999003, 999004, 999005, 999006, 999007, 999008, 999009]

0.64seconds

这个实现的特点是,使用了数组,而不是双端队列来作为基础存储数据结构。当然由于Ring Buffer的访问特性,我们也基本上只对队头、队尾元素进行操作,所以无论是使用数组还是双端队列,操作复杂度都是O(1)。

另一个值得一提的点是,它使用了动态改变对象_class_实现的方式,避免了不必要的判断语句操作,即在创建之初,缓冲区未满时,每插入一个元素,都要在第19行处进行一次判断;而一旦缓冲区被充满后,RingBuffer对象升级为__Full类,从而行为也从此改变--今后再向缓冲区添加新的元素时,不再进行条件语句判断。

尽管代码做了足够的优化,python内建dequeue的实现性能更高一些。

# 使用C语言的实现-pyringbuf

[sirlark](#sirlark)用C语言实现了一个开源的[RingBuffer](#pyringbuf 0.1b2 : Python Package Index),可以通过pip来安装使用。

pip install pyringbuf

这个模块提供了push, pop, write, read等函数,使用示例如下:

>>> from ringbuf import RingBuffer

>>> R = RingBuffer(5) #choose your buffer size

>>> R.push("a") #push a single character into the buffer

>>> R.pop() #pop a single character

'a'

>>> R.write("bcdef") #fill buffer with many characters at once

>>> R.read(4) #read many characters at once

'bcde'

>>> R.read(1)

'f'

>>> R.read(1) #returns an empty string if the buffer is empty

这个模块以c语言源码提供,使用前需要编译。

c ringbuffer 源码_Python Ring Buffer的实现相关推荐

  1. mysql buffer 命中率_从MySQL的源码剖析Innodb buffer的命中率计算

    按官方手册推荐Innodb buffer Hit Ratios的计算是: 100-((iReads / iReadRequests)*100) iReads : mysql->status-&g ...

  2. [NIO系列]NIO源码分析之Buffer

    在以前的一篇文章中我们介绍过IO模型 IO模型总结 http://www.cnblogs.com/coldridgeValley/p/5449758.html ,而在实际运用中多路复用IO使用很多,J ...

  3. python爬网页源码_python爬虫爬取网页的内容和网页源码不同?

    可以看到这里id为k_total的元素值不同,爬出来是1,网页源码是55. 附还未完成的代码:import requests from bs4 import BeautifulSoup import ...

  4. python算法实现源码_python 实现A_算法的示例代码

    python 实现A_算法的示例代码 来源:中文源码网    浏览: 次    日期:2018年9月2日 [下载文档:  python 实现A_算法的示例代码.txt ] (友情提示:右键点上行txt ...

  5. python关键词提取源码_Python 结巴分词 关键词抽取分析

    关键词抽取就是从文本里面把跟这篇文档意义最相关的一些词抽取出来.这个可以追溯到文献检索初期,当时还不支持全文搜索的时候,关键词就可以作为搜索这篇论文的词语.因此,目前依然可以在论文中看到关键词这一项. ...

  6. delphi gui编辑工具源码_Python 快速构建一个简单的 GUI 应用

    点击上方"AirPython",选择"加为星标" 第一时间关注 Python 技术干货! 1. 介绍 Python GUI 常用的 3 种框架是:Tkinter ...

  7. python人脸识别源码_Python 抖音机器人,让你找到漂亮小姐姐

    本项目作者沉迷于抖音无法自拔,常常花好几个小时在抖音漂亮小姐姐身上. 本着高效.直接地找到漂亮小姐姐的核心思想,我用 Python + ADB 做了一个 Python 抖音机器人 Douyin-Bot ...

  8. android 小游戏源码_Python入门太难?不如从玩塔防小游戏开始,玩通关就能学会编程...

    我一直认为,在python入门阶段学习基础理论,太枯燥.所以我们整理了很多有关python的项目案例,有详细教程还有源码,希望能帮助更多对python感兴趣的人. 这是其中一个适合入门的Python项 ...

  9. python贪吃蛇源码_Python:游戏:贪吃蛇(附源码)

    Python:游戏:贪吃蛇(附源码) 发布时间:2018-09-05 09:59, 浏览次数:1295 , 标签: Python 贪吃蛇是个非常简单的游戏,适合练手. 首先分析一下这个游戏 1.蛇怎么 ...

  10. python爬虫框架源码_python爬虫的基本框架

    1.爬虫的基本流程: 通过requests库的get方法获得网站的url 浏览器打开网页源码分析元素节点 通过BeautifulSoup或者正则表达式提取想要的数据 储存数据到本地磁盘或者数据库 2. ...

最新文章

  1. 本站将进行有关《大道至简》的讨论~
  2. jQuery 要点总结
  3. 左耳朵耗子论微服务 Serverless 及 FaaS | GIAC 访谈
  4. 第三百一十节,Django框架,模板语言
  5. 公用表表达式(CTE)WITH:树型查询、更新
  6. 邻接表的两种实现(链表和数组模拟)
  7. 面向对象的三大特征之一继承
  8. 编译 php7,编译PHP7
  9. 【推荐】前沿智能视频分析深度学习算法框架-NVIDIA DEEPSTREAM5.0 【原理介绍】
  10. 基于三极管的电平转换电路
  11. centos防火墙的关闭,硬盘挂载,yum配置,创建实验快照
  12. 运营商价格战终于打起来了,中国联通也有19元套餐
  13. 委托、事件 茴字有几种写法
  14. 古剑奇谭ol服务器位置,国产网游史上第一次?古剑奇谭OL将把WeGame与360服务器数据互通...
  15. ASU计算机科学专业大学排名,2013年U.S.News美国大学排名--计算机科学专业研究生排名...
  16. 解决戴尔电脑耳机插入后无效,外放正常的问题
  17. 猎聘、BOSS、智联、前程无忧这几个招聘网站我都用过
  18. iOS基础 获取状态栏的高度
  19. ESA SNAP工具包Java接口的使用
  20. 刚才桌子上洒水了,好干净!

热门文章

  1. 经典的出入库算法(C#实现)
  2. python基础学习笔记1
  3. 平衡的阵容——洛谷——2880——RMQ
  4. echars的矩形数图根据大小根据一个值变化,颜色跟随另外一个值变化
  5. webots自学笔记(五)使用物理插件ODE建立铰链
  6. oracle在cmd中启动数据库实例
  7. Spring源码之FactoryBean接口的作用和实现原理
  8. Spring中的@Autowired自动装配
  9. Grafana 安装和使用
  10. Facebook广告目标摘要