Python Sequence
What Is a Sequence?
A sequence in Python is an ordered collection of items, where each item can be accessed by its integer index. Sequences are fundamental data structures, and common built-in examples include lists, tuples, and strings.
The collections.abc.Sequence
abstract base class (ABC) defines the common interface for immutable sequence types. It inherits from Reversible
and Collection
, meaning a Sequence
is also expected to be sized, iterable, a container, and reversible.
Required Methods and Inherited Functionality
To conform to the Sequence
ABC, a class primarily needs to implement:
__getitem__(self, index)
: Returns the item at the givenindex
. This method also supports slicing.__len__(self)
: (Inherited fromSized
) Returns the number of items in the sequence.
From its parent ABCs (Collection
and Reversible
), Sequence
automatically gains mixin methods for:
__contains__
(using__getitem__
and__len__
)__iter__
(using__getitem__
and__len__
)__reversed__
(using__getitem__
and__len__
)count
index
from collections.abc import Sequence
from typing import Any, Iterator, Union
class MyImmutableSequence(Sequence):
def __init__(self, *elements: Any) -> None:
self._data = tuple(elements) # Immutable internal storage
def __getitem__(self, index: Union[int, slice]) -> Any:
return self._data[index]
def __len__(self) -> int:
return len(self._data)
# The following methods are provided by the Sequence ABC mixins
# but can be overridden for performance if needed:
# def __contains__(self, item: Any) -> bool:
# return item in self._data
# def __iter__(self) -> Iterator[Any]:
# return iter(self._data)
# def __reversed__(self) -> Iterator[Any]:
# return reversed(self._data)
# def count(self, value: Any) -> int:
# return self._data.count(value)
# def index(self, value: Any, start: int = 0, stop: int = None) -> int:
# return self._data.index(value, start, stop)
# Example usage:
my_seq = MyImmutableSequence(10, 20, 30, 'a', 'b')
print(f"Length: {len(my_seq)}") # Output: Length: 5
print(f"Item at index 1: {my_seq[1]}") # Output: Item at index 1: 20
print(f"Slice [2:4]: {my_seq[2:4]}") # Output: Slice [2:4]: (30, 'a')
print(f"Contains 'a'? {'a' in my_seq}") # Output: Contains 'a'? True
print("Iterating:")
for item in my_seq:
print(item)
print("Reversed:")
for item in reversed(my_seq):
print(item)
Using collections.abc.Sequence
You can check if a class or object is a sequence using isinstance
or issubclass
:
from collections.abc import Sequence
class AnotherSequence:
def __init__(self, data: list) -> None:
self._data = data
def __getitem__(self, index: Union[int, slice]) -> Any:
return self._data[index]
def __len__(self) -> int:
return len(self._data)
print(issubclass(AnotherSequence, Sequence)) # True
print(isinstance(AnotherSequence([1,2,3]), Sequence)) # True
# Built-in sequence types also conform:
print(isinstance([], Sequence)) # True (list)
print(isinstance((), Sequence)) # True (tuple)
print(isinstance("hello", Sequence)) # True (str)
It's generally recommended to inherit directly from collections.abc.Sequence
(or other relevant ABCs) when designing your custom sequence classes. This makes your code more explicit about its intended interface and can help static analysis tools. However, it's not strictly mandatory; Python's duck typing means that if your class implements the required __getitem__()
and __len__()
methods, it will be recognized as a sequence, even without explicit inheritance from the ABC.
Key Takeaways
- A
Sequence
is an ordered collection accessible by index. - It primarily requires
__getitem__()
and__len__()
. - It inherits functionality from
Collection
andReversible
.