add maxlen for deque

This commit is contained in:
blueloveTH 2025-09-08 20:07:54 +08:00
parent d3d61dde0c
commit f12a379760
3 changed files with 60 additions and 12 deletions

View File

@ -27,20 +27,29 @@ class defaultdict(dict):
class deque[T]:
_data: list[T]
_head: int
_tail: int
_maxlen: int | None
_capacity: int
_data: list[T]
def __init__(self, iterable: Iterable[T] = None, maxlen: int | None = None):
if maxlen is not None:
assert maxlen > 0
def __init__(self, iterable: Iterable[T] = None):
self._data = [None] * 8 # type: ignore
self._head = 0
self._tail = 0
self._capacity = len(self._data)
self._maxlen = maxlen
self._capacity = 8 if maxlen is None else maxlen + 1
self._data = [None] * self._capacity # type: ignore
if iterable is not None:
self.extend(iterable)
@property
def maxlen(self) -> int | None:
return self._maxlen
def __resize_2x(self):
backup = list(self)
self._capacity *= 2
@ -51,19 +60,25 @@ class deque[T]:
self._data.extend([None] * (self._capacity - len(backup)))
def append(self, x: T):
if (self._tail + 1) % self._capacity == self._head:
if self._maxlen is None:
self.__resize_2x()
else:
self.popleft()
self._data[self._tail] = x
self._tail = (self._tail + 1) % self._capacity
if (self._tail + 1) % self._capacity == self._head:
self.__resize_2x()
def appendleft(self, x: T):
if (self._tail + 1) % self._capacity == self._head:
if self._maxlen is None:
self.__resize_2x()
else:
self.pop()
self._head = (self._head - 1) % self._capacity
self._data[self._head] = x
if (self._tail + 1) % self._capacity == self._head:
self.__resize_2x()
def copy(self):
return deque(self)
return deque(self, maxlen=self.maxlen)
def count(self, x: T) -> int:
n = 0
@ -84,12 +99,15 @@ class deque[T]:
if self._head == self._tail:
raise IndexError("pop from an empty deque")
self._tail = (self._tail - 1) % self._capacity
return self._data[self._tail]
x = self._data[self._tail]
self._data[self._tail] = None
return x
def popleft(self) -> T:
if self._head == self._tail:
raise IndexError("pop from an empty deque")
x = self._data[self._head]
self._data[self._head] = None
self._head = (self._head + 1) % self._capacity
return x
@ -144,5 +162,7 @@ class deque[T]:
return not self == other
def __repr__(self) -> str:
return f"deque({list(self)!r})"
if self.maxlen is None:
return f"deque({list(self)!r})"
return f"deque({list(self)!r}, maxlen={self.maxlen})"

File diff suppressed because one or more lines are too long

View File

@ -516,3 +516,31 @@ d = deque()
for i in range(100):
d.append(1)
gc.collect()
# test maxlen
q = deque(maxlen=3)
assertEqual(q.maxlen, 3)
q.append(1)
q.append(2)
q.append(3)
assertEqual(list(q), [1, 2, 3])
assertEqual(q._data, [1, 2, 3, None])
q.append(4)
assertEqual(list(q), [2, 3, 4])
assertEqual(q._data, [None, 2, 3, 4])
q.appendleft(1)
assertEqual(list(q), [1, 2, 3])
assertEqual(q._data, [1, 2, 3, None])
q.appendleft(0)
assertEqual(list(q), [0, 1, 2])
assertEqual(q._data, [1, 2, None, 0])
q.pop()
assertEqual(list(q), [0, 1])
assertEqual(q._data, [1, None, None, 0])
assertEqual(len(q), 2)
assertEqual(q._capacity, 4)
q.popleft()
assertEqual(list(q), [1])
assertEqual(q._data, [1, None, None, None])