Skip to content

Commit c3ddeba

Browse files
feat: add __str__ methods and pytest-benchmark support
Add human-friendly __str__ to all data structures (arrow notation for linked lists and stacks, plain list for arrays) and integrate pytest-benchmark for performance testing.
1 parent 628bc40 commit c3ddeba

16 files changed

Lines changed: 290 additions & 31 deletions

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ s.push(2)
2323
s.peek() # 2
2424
s.pop() # 2
2525
s.size() # 1
26+
repr(s) # "ArrayStack([1])"
27+
str(s) # "1"
2628

2729
ms = MinStack()
2830
ms.push(5)
@@ -43,6 +45,8 @@ from data_structures.array.static_array import StaticArray
4345
from data_structures.array.dynamic_array import DynamicArray
4446

4547
sa = StaticArray([1, 2, 3]) # or StaticArray(3) for empty
48+
repr(sa) # "StaticArray([1, 2, 3])"
49+
str(sa) # "[1, 2, 3]"
4650
list(sa) # [1, 2, 3]
4751
sa.pop() # 3
4852
sa.insert(0, 0)
@@ -70,13 +74,15 @@ sll = SinglyLinkedList()
7074
sll.push_front(1)
7175
sll.push_front(2)
7276
sll.peek_front() # 2
77+
str(sll) # "2 -> 1"
7378
sll.pop_front() # 2
7479
list(sll) # [1]
7580

7681
dll = DoublyLinkedList()
7782
dll.push_front(1)
7883
dll.push_back(2)
7984
dll.push_back(3)
85+
str(dll) # "1 <-> 2 <-> 3"
8086
dll.peek_back() # 3
8187
dll.pop_back() # 3
8288
list(dll) # [1, 2]
@@ -123,6 +129,9 @@ uv sync --group dev
123129
# Run tests (with coverage)
124130
uv run pytest tests/ -v
125131

132+
# Run benchmarks
133+
uv run pytest tests/test_benchmarks.py --benchmark-enable --no-cov
134+
126135
# Lint & format
127136
uv run ruff check .
128137
uv run ruff format .
@@ -159,6 +168,7 @@ tests/
159168
test_stacks.py # pytest suite for stack implementations
160169
test_linked_lists.py # pytest suite for linked list implementations
161170
test_binary_search.py # pytest suite for binary search
171+
test_benchmarks.py # pytest-benchmark performance tests
162172
.pre-commit-config.yaml # pre-commit hooks (ruff, ty)
163173
pyproject.toml # project config, tools settings
164174
```

data_structures/array/base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,8 @@ def __contains__(self, item: object) -> bool:
6161

6262
@abstractmethod
6363
def __repr__(self) -> str:
64-
"""Return a string representation."""
64+
"""Return a developer-friendly representation (e.g. ``StaticArray([1, 2])``)."""
65+
66+
@abstractmethod
67+
def __str__(self) -> str:
68+
"""Return a human-friendly string (e.g. ``[1, 2]``)."""

data_structures/array/dynamic_array.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,13 @@ def __contains__(self, item: object) -> bool:
119119
return any(v == item for v in self)
120120

121121
def __repr__(self) -> str:
122-
"""Return a string representation."""
122+
"""Developer-friendly representation (e.g. ``DynamicArray([1, 2])``)."""
123123
return f"{type(self).__name__}({list(self)})"
124124

125+
def __str__(self) -> str:
126+
"""Return a human-friendly string (e.g. ``[1, 2]``)."""
127+
return str(list(self))
128+
125129
def _normalize_index(self, index: int) -> int:
126130
"""Translate negative indices and validate bounds."""
127131
if index < 0:

data_structures/array/static_array.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,13 @@ def __contains__(self, item: object) -> bool:
121121
return any(v == item for v in self)
122122

123123
def __repr__(self) -> str:
124-
"""Return a string representation."""
124+
"""Return a developer-friendly representation (e.g. ``StaticArray([1, 2])``)."""
125125
return f"{type(self).__name__}({list(self)})"
126126

127+
def __str__(self) -> str:
128+
"""Return a human-friendly string (e.g. ``[1, 2]``)."""
129+
return str(list(self))
130+
127131
def _normalize_index(self, index: int) -> int:
128132
"""Translate negative indices and validate bounds."""
129133
if index < 0:

data_structures/linked_list/base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ def __contains__(self, item: object) -> bool:
4949

5050
@abstractmethod
5151
def __repr__(self) -> str:
52-
"""Return a string representation."""
52+
"""Return a developer-friendly representation."""
53+
54+
@abstractmethod
55+
def __str__(self) -> str:
56+
"""Return a human-friendly string (e.g. ``1 -> 2 -> 3``)."""
5357

5458

5559
class IDoublyLinkedList[T](ISinglyLinkedList[T]):

data_structures/linked_list/doubly_linked_list.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,6 @@ def __contains__(self, item: object) -> bool:
9797

9898
def __repr__(self) -> str:
9999
return f"{type(self).__name__}({list(self)})"
100+
101+
def __str__(self) -> str:
102+
return " <-> ".join(str(v) for v in self) if self._head else "empty"

data_structures/linked_list/singly_linked_list.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,6 @@ def __contains__(self, item: object) -> bool:
5555

5656
def __repr__(self) -> str:
5757
return f"{type(self).__name__}({list(self)})"
58+
59+
def __str__(self) -> str:
60+
return " -> ".join(str(v) for v in self) if self._head else "empty"

data_structures/stack/array_stack.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,7 @@ def __contains__(self, item: object) -> bool:
3636

3737
def __repr__(self) -> str:
3838
return f"{type(self).__name__}({list(self._items)})"
39+
40+
def __str__(self) -> str:
41+
items = list(self._items)
42+
return " -> ".join(str(v) for v in reversed(items)) if items else "empty"

data_structures/stack/base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,8 @@ def __contains__(self, item: object) -> bool:
5151

5252
@abstractmethod
5353
def __repr__(self) -> str:
54-
"""Return a string representation."""
54+
"""Return a developer-friendly representation."""
55+
56+
@abstractmethod
57+
def __str__(self) -> str:
58+
"""Return a human-friendly string (top → bottom)."""

data_structures/stack/linked_list_stack.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ def __contains__(self, item: object) -> bool:
3939

4040
def __repr__(self) -> str:
4141
return f"{type(self).__name__}({list(self._items)})"
42+
43+
def __str__(self) -> str:
44+
items = list(self._items)
45+
return " -> ".join(str(v) for v in items) if items else "empty"

0 commit comments

Comments
 (0)