定义一个固定大小的缓存,当它被填满时,新加入的元素自动覆盖第一个元素,这种方法经常用在存储日志和历史信息的程序中。
[root@xiaoxiong cb6]# cat cb2_6_11_sol_1.py
class RingBuffer(object):
""" class that implements a not-yet-full buffer """
def __init__(self, size_max):
self.max = size_max
self.data = []
class __Full(object):
""" 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 tolist(self):
""" return list of elements in correct order. """
return self.data[self.cur:] + self.data[:self.cur]
def append(self, x):
""" append an element at the end of the buffer. """
self.data.append(x)
if len(self.data) == self.max:
self.cur = 0
#当队列满时将self的类从非满改为满
self.__class__ = self.__Full
def tolist(self):
""" Return a list of elements from the oldest to the newest. """
return self.data
# sample usage
if __name__ == '__main__':
x = RingBuffer(5)
x.append(1); x.append(2); x.append(3); x.append(4)
print x.__class__, x.tolist()
x.append(5)
print x.__class__, x.tolist()
x.append(6)
print x.data, x.tolist()
x.append(7); x.append(8); x.append(9); x.append(10)
print x.data, x.tolist()
[root@xiaoxiong cb6]#
[root@xiaoxiong cb6]# python cb2_6_11_sol_1.py
<class '__main__.RingBuffer'> [1, 2, 3, 4]
<class '__main__.__Full'> [1, 2, 3, 4, 5]
[6, 2, 3, 4, 5] [2, 3, 4, 5, 6]
[6, 7, 8, 9, 10] [6, 7, 8, 9, 10]
[root@xiaoxiong cb6]#
值得注意的地方是,我通过修改self.__class__来完成这种转变:
self.__class__ = self.__Full
当环填满时,给__class__赋值以改变其行为方式,这种切换类的方法效率非常高,这种类转换是一次性的操作,所以它不会带来任何性能上的开销。可以参考下文通过切换实例方法来实现的技巧。