77

I would like to know if there is a native datatype in Python that acts like a fixed-length FIFO buffer. For example, I want do create a length-5 FIFO buffer that is initialized with all zeros. Then, it might look like this:

[0,0,0,0,0]

Then, when I call the put function on the object, it will shift off the last zero and put the new value, say 1, into the left side:

[1,0,0,0,0]

If I put a 2, it would then shift and put to look like this:

[2,1,0,0,0]

...and so on. The new value goes at the front and the oldest one is shifted off. I understand that this would be very easy to implement myself, but I would like to use native python datatypes if at all possible. Does anyone know which datatype would be best for this?

mattdm
  • 2,082
  • 25
  • 39
Doughy
  • 4,115
  • 6
  • 36
  • 39

4 Answers4

116
x = collections.deque(5*[0], 5)

See the docs for more about collections.deque; the method you call push is actually called appendleft in that type.

The second parameter (maxlen, giving the maximum lengths) was added in Python 2.6; if you're using older versions of Python, it won't be available.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
12

you can also use list

a = [0,0,0,0,0]

a.pop(0)
a.append(1)

print a
result [0,0,0,0,1]

or for left side in right out, otherwise

a.pop(5)
a.insert(0,1)
print a
result [1,0,0,0,0]
Edo
  • 185
  • 1
  • 2
  • 3
    -1 This is not recommended. For reason why read the docs http://docs.python.org/library/collections.html?highlight=collections.deque#collections.deque – toom Feb 07 '14 at 18:05
  • 3
    @toom it isn't not recommended, you just need to be aware of the penalty of using lists. For simplicity, a list is hard to beat. – Henry Gomersall Dec 27 '14 at 17:34
  • This is a bad solution. I implemented it using a list with a fixed number of elements and an index counter. – Bachsau Sep 24 '19 at 12:47
  • -1 first example is not a FIFO, it is a LIFO. The second example it is indeed a FIFO, although it's an extremely slow one and not recommented. collections.deque is a much faster one, with O(1) complexity for appendleft, instead of list.seek(0,1) which has complexity equal to list length. – Aristotelis V Mar 30 '21 at 15:53
8

Just one more example to this post

from collections import deque

domains = ['1.com','2.com','3.com']
d = deque(domains)               
d.pop() #pop(delete) 3.com here
d.appendleft('new.com') 


print d

result:

deque(['new.com', '1.com', '2.com'])
John
  • 23,360
  • 7
  • 57
  • 83
derevo
  • 9,048
  • 2
  • 22
  • 19
  • 1
    Why you use pop and not maxlen ? – Mr_and_Mrs_D Dec 17 '17 at 13:17
  • 1
    I'ts not what's happening in this example, but you may want to catch the item that falls off the buffer. For that, use pop: `fell_off = d.pop(); d.appendleft(new)`. – Puff Nov 15 '18 at 15:05
3

test_queue = deque([0]*5,maxlen=5) 

for i in range(10):
    print(i)
    test_queue.appendleft(i)
    print(list(test_queue))

prints:

[0, 0, 0, 0, 0]
1
[1, 0, 0, 0, 0]
2
[2, 1, 0, 0, 0]
3
[3, 2, 1, 0, 0]
4
[4, 3, 2, 1, 0]
5
[5, 4, 3, 2, 1]
6
[6, 5, 4, 3, 2]
7
[7, 6, 5, 4, 3]
8
[8, 7, 6, 5, 4]
9
[9, 8, 7, 6, 5]
YScharf
  • 1,638
  • 15
  • 20