Хорошо написанный код на Python должен работать с последовательностями однообразно. При этом неважно, встроенные это последовательности или нет. Тем более что свою последовательность написать в Python очень просто. Нужно всего лишь переопределить __len__ и __getitem__, чтобы работа с вашей последовательностью в большинстве случаев не отличалась от работы со встроенными последовательностями.

В качестве иллюстрации возьмём такой пример. У нас есть класс ShoppingBasket. В нём лежат какие‑то товары. Пусть нам нужно пройтись по всем товарам, научиться получать товары по ключу и добавлять товары.

Первый вариант

Положимся на встроенные коллекции. Для хранения элементов используем список.

# -*- coding: utf-8 -*-
from collections import namedtuple

BasketItem = namedtuple('BasketItem', 'name, price, quantity')

class ShoppingBasket(object):
    def __init__(self):
        self.items = []

if __name__ == '__main__':
    basket = ShoppingBasket()
    basket.items = [
        BasketItem("Apple", 1.12, 2),
        BasketItem("Orange", 1.3, 4),
    ]

    # печатаем содержимое
    for item in basket.items:
        print(item)

    # только яблоки
    print("Apples:", basket.items[0])

    # всего элементов в корзине
    print("Items:", len(basket.items))

Код работает. Но у него большая проблема: класс ShoppingBasket открывает наружу то, как он хранит товары в корзине. Этот код жёстко привязывает нас к списку. Если по каким‑то причинам мы захотим поменять модель хранения товаров в корзине (привязать к БД, например), то придётся править код во множестве мест, где имеется работа с корзиной. Нам повезёт, если код не является частью публичного API.

Второй вариант

Попробуем спрятать зависимость от внутренней структуры данных внутри корзины.

# -*- coding: utf-8 -*-
from collections import namedtuple

BasketItem = namedtuple('BasketItem', 'name, price, quantity')

class ShoppingBasket(object):
    def __init__(self):
        self.items = []

    def append(self, value):
        self.items.append(value)

    def __getitem__(self, key):
        return self.items[key]

    def __len__(self):
        return len(self.items)

if __name__ == '__main__':
    basket = ShoppingBasket()
    basket.append(BasketItem("Apple", 1.12, 2))
    basket.append(BasketItem("Orange", 1.3, 4))
    basket.append(BasketItem("Bananas", 0.8, 1))

    # печатаем содержимое
    for item in basket:
        print(item)

    # только яблоки
    print("Apples:", basket[0])

    # слайсы также работают
    print(basket[:2])

    # всего элементов в корзине
    print("Items:", len(basket))

Код внутри __main__ стал более аккуратным. Зависимость от способа хранения элементов убрана в класс корзины. Переделать этот вариант корзины на хранение элементов в БД с сохранением интерфейса не составит проблем.

Не ленитесь. Если ваш класс по сути — коллекция, прячьте то, как он хранит свои элементы, но делайте привычные интерфейсы. Так вы облегчите жизнь себе и пользователям вашего кода.