Lista circular em python

Essa semana que passou eu fui praticar um pouco de python e testes, dessa vez tentando montar uma lista circular em python.
A ideia é montar como se fosse um carrossel, com a diferença de pudesse avançar e retroceder infinitamente, sem que disparasse um erro quando chegasse no final.
Essa ideia veio logo após terminar de assistir ao curso de estruturas de dados da Staart que adquiri outro dia.
Os códigos estão nesse repositório do Github https://github.com/kylefelipe/estrutura-de-dados-lista-duplamente-ligada-carrossel, podendo ser clonado, “forkado” ou baixado, o que for de sua preferência fazer.
Issues com sugestões são bem vindas no repositório.
O que é uma lista duplamente ligada?
É uma lista onde o item atual guarda a referência do item anterior e do próximo item, permitindo ir pra frente e para trás na estrutura sem precisar ficar calculando os índices para onde estamos indo.
Ainda é necessário fazer uma certa implementação dos nós do item, mas com esse código de exemplo já é possível fazer o avanço (usando o next()) ou retrocesso (nesse caso, usando Carousel.prev()).
O que é uma lista circular?
Uma Lista circular aquela que, quando estamos no último elemento (nó) e tentamos avançar para o próximo, retornamos automaticamente para o primeiro, e no nosso caso, se estivermos no primeiro item e retrocedermos, iremos para o último item da lista.
Em uma lista normal, ao tentar avançar para o próximo item no final de uma lista, recebemos uma mensagem de StopIteration, ou alguma mensagem de erro, o que não ocorre em listas circulares (por isso dei o nome de carrossel nesse exemplo).
E os testes?
Para treinar, criei uma série de testes utilizando a biblioteca do python chamada Pyteste, lá estão muitos casos que utilizei para fazer os testes, e estão beeeeem simples, mesmo para quem tem pouco contato com os testes conseguirá entender o que tem ocorrido.
Para utilizálos, basta criar um ambiente virtual com a sua biblioteca preferida e instalar as dependências que estão dentro do arquivo dev_requirements.
Aqui vai um exemplo de como criar um ambiente usando o venv:
python3 -m venv .venv
source .venv/bin/activate # Ativando o ambiente - considere o shel que estiver usando
(.venv) pip install -r dev_requirements # Instalar as libs necessárias no python do ambiente
Métodos do carrossel
Tentei implementar boa parte dos métodos de uma lista normal, como inserir e remover itens, e alguns que nem sempre são vistos no dia a dia, com por exemplo um método .prev().
O método .prev() é responsável por retroceder na lista, caso não tenha sido utilizado o método .prev(), .next() ou não tenha iniciado a instância em uma determinada posição, o método irá para o último item da lista.
carrossel = Carousel(['Profa. Helena Fernandez', 'Maria Joaquina', 'Cirilo Rivera', 'Suzana Bustamante', 'Carmen Carrillo', 'Jaime Palillo'])
print(f"Tamanho do carrossel: {len(carrossel)}")
# 6
print(f"Posição atual: {carrossel.posicao} - Item Atual: {carrossel.atual}")
# Posição atual: None - Item Atual: None
anterior = carrossel.prev()
print(f"Item anterior: {anterior}")
#> Item anterior: Jaime Palillo
print(f"Posição atual: {carrossel.posicao} - Item Atual: {carrossel.atual}")
# Posição atual: 3 - Item Atual: Jaime Palillo
print(f"Tamanho do carrossel: {len(carrossel)}")
# Tamanho do carrossel: 6
Já o método .posicao indica a posição atual na estrutura, que por padrão é None, caso não tenha sido indicado uma posição inicial.
carrossel = Carousel(['Profa. Helena Fernandez', 'Maria Joaquina',
'Cirilo Rivera', 'Suzana Bustamante', 'Carmen Carrillo', 'Jaime Palillo'], 2)
print(
f"Posição atual: {carrossel.posicao} - Item Atual: {carrossel.atual}")
# > Posição atual: 2 - Item Atual: Cirilo Rivera
O método .atual indica a posição atual na estrutura, e tem por padrão o valor None:
print(f'item atual: {carrossel_original.atual}')
#>> None
print(f'Posição atual: {carrossel_original.posicao}')
#>> None
carrossel_original.next()
print(f'item atual: {carrossel_original.atual}')
#>> Profa. Helena Fernandez
print(f'item atual: {carrossel_original.posicao}')
#>> 0
Considerações finais
No repositório tem um arquivo com exemplos de uso do carrossel (o arquivo exemplos.py), que não precisa de nenhuma instalação adicional no python, sendo possível rodar o arquivo sem a criação de ambiente próprio.
Foi um exercício muito bacana de se fazer, mas ainda há boas coisas a se fazer, como por exemplo, criar uma classe _Nó com alguns atributos mais elaborados.
Nos testes, falta fazer alguns para os casos quando iniciamos instância com uma posição já definida, essa parte já está pronta no carrossel mas não há testes ainda.
Visite o repositório do Github para ver a explicação de cada parte da estrutura criada (clique aqui).
Caso queiram saber um pouco mais sobre python, clique aqui.
Caso tenham interesses em cursos sobre python, aqui tem alguns.