Python UserList: Custom Sequences

Published on: August 30, 2026
Reading time: 2 minutes
Close-up of vibrant JavaScript code featuring functions and syntax highlighting.

collections.UserList is a helper class for building custom mutable sequences. It stores elements in a regular list exposed through data and offers a predictable extension surface for validation, normalization, logging, and domain rules.

It is useful when a collection should behave like a list but must control insertions, replacements, deletion, accepted types, or batch operations.

Basic example

from collections import UserList

class IntegerList(UserList):
    def _validate(self, value):
        if not isinstance(value, int):
            raise TypeError("integers only")
        return value

    def append(self, value):
        super().append(self._validate(value))

    def insert(self, index, value):
        super().insert(index, self._validate(value))

Validating only append is not enough. A list can also change through index assignment, slices, extend, and +=.

Covering mutation paths

class IntegerList(UserList):
    def _validate(self, value):
        if not isinstance(value, int):
            raise TypeError("integers only")
        return value

    def __setitem__(self, index, value):
        if isinstance(index, slice):
            value = [self._validate(item) for item in value]
        else:
            value = self._validate(value)
        super().__setitem__(index, value)

    def append(self, value):
        super().append(self._validate(value))

    def insert(self, index, value):
        super().insert(index, self._validate(value))

    def extend(self, values):
        super().extend(self._validate(item) for item in values)

The data attribute

data contains the actual list. Direct changes can bypass validation, so treat it as an implementation detail.

Normalizing values

class Tags(UserList):
    def _normalize(self, value):
        text = str(value).strip().casefold()
        if not text:
            raise ValueError("empty tag")
        return text

Decide whether duplicates are valid. If uniqueness is the main rule, a set or mapping may model the domain better.

UserList versus list subclassing

A direct list subclass may be faster and can be required by APIs expecting the concrete type. UserList prioritizes extensibility and routes operations through methods that are easier to customize.

UserList versus MutableSequence

Implement MutableSequence when storage is not an ordinary list, such as disk-backed data, a virtual window, or a compact structure. Choose UserList when an internal list is sufficient.

Operations returning new sequences

Test concatenation, multiplication, slicing, and copying. Define whether results should preserve the custom class or become normal lists.

Sorting and instrumentation

class Tasks(UserList):
    def sort(self, *, key=None, reverse=False):
        log("sorting tasks")
        super().sort(key=key, reverse=reverse)

Avoid expensive or surprising side effects in familiar list operations.

Serialization

Some serializers require a concrete list. Convert explicitly:

import json
json.dumps(list(values))

Common mistakes

  • Validating only append.
  • Ignoring slice assignment and extend.
  • Changing data directly.
  • Using a list when uniqueness is required.
  • Assuming the result type of slicing or concatenation.

Inventory every mutation path, centralize validation, call super(), test operators, and document result types. See the internal guides to Python lists and collections.

Conclusion

UserList is a practical base for custom sequences backed by a regular list. It helps enforce consistent invariants without depending on list implementation details.

External sources

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    Code and XML structure for canonicalization with Python
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    ElementTree canonicalize: Normalize XML in Python

    Learn Python ElementTree canonicalize for stable XML comparisons, hashes, namespaces, comments, and signature preparation.

    Ler mais

    Tempo de leitura: 5 minutos
    22/10/2026
    Python programming code displayed on a screen
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    T-strings and templatelib: Structured Interpolation

    Learn Python t-strings and string.templatelib for structured interpolation, safer renderers, logging, and custom processing.

    Ler mais

    Tempo de leitura: 5 minutos
    22/10/2026
    SQLite database and Python code for selective iterdump export
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    SQLite iterdump: Create Selective Dumps in Python

    Learn sqlite3.Connection.iterdump filters for selective SQLite dumps, dependency checks, validation, and safer restoration.

    Ler mais

    Tempo de leitura: 4 minutos
    21/10/2026
    Code and files representing Python data compression
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: Fast Zstandard in Python

    Learn Python compression.zstd for fast file and data compression, streaming, integrity checks, and safe decompression.

    Ler mais

    Tempo de leitura: 7 minutos
    21/10/2026
    Configuration file and code structure for Python ConfigParser
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    ConfigParser: Read INI Files Without Sections

    Learn Python ConfigParser unnamed sections with validation, typed values, compatibility, layered settings, and safe INI writing.

    Ler mais

    Tempo de leitura: 5 minutos
    20/10/2026
    Binary data and computer memory representing Python memoryview
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    memoryview count and index: Search Without Copies

    Learn Python memoryview count and index to search values in zero-copy buffers and validate binary data efficiently.

    Ler mais

    Tempo de leitura: 5 minutos
    20/10/2026