Search code examples
pythondeque

python deque understanding


I came across a bit of code in StackOverflow that raised two questions about the way deque works. I don't have enough reputation to ask "in situ", therefore this question:

from collections import deque
from itertools import islice

def sliding_window(iterable, size=2, step=1, fillvalue=None):
    if size < 0 or step < 1:
        raise ValueError
    it = iter(iterable)
    q = deque(islice(it, size), maxlen=size)
    if not q:
        return  # empty iterable or size == 0
    q.extend(fillvalue for _ in range(size - len(q)))  # pad to size
    while True:
        yield iter(q)  # iter() to avoid accidental outside modifications
        q.append(next(it))
        q.extend(next(it, fillvalue) for _ in range(step - 1))

The code computes a sliding window of a given size over a sequence. The steps I don't understand are first:

q = deque(islice(it, size), maxlen=size)

What is the use of maxlen here? Isn't islice always going to output an iterable of at most length size?

And second:

yield iter(q)  # iter() to avoid accidental outside modifications

why do we need to transform to to iterable to avoid "accidental outside modifications"?


Solution

  • To answer second part of the question, everything in Python is passed by reference. So in case of above generator q is a reference to the original deque hold by the function, so any method that may amend the deque, would break original algorithm of the generation. When you surround q with iter() what you effectively have yielded is an iterator. You can take elements from iterator (read), but you cannot change elements itself or amend the sequence of them (write not allowed). So it's a good practice to protect from accidental damage to the container hold internally be the generator.