Como usar a deque do Python?
Python’s deque: Implementar filas e pilhas eficientes
Se você trabalha frequentemente com listas em Python, provavelmente sabe que elas não têm um desempenho rápido o suficiente quando você precisa retirar (pop
) e adicionar (append
) itens no início da lista. O módulo collections
do Python fornece uma classe chamada deque
que foi especialmente projetada para fornecer formas rápidas e eficientes de anexar e remover itens de ambos os extremos da estrutura de dados subjacente.
O deque
do Python é uma fila de dois extremos otimizada e de baixo nível que é útil para implementar filas e pilhas elegantes, eficientes e com a sintaxe do Python, que são os tipos de dados de lista mais comuns na computação.
Neste tutorial, você aprenderá:
- Como criar e usar o
deque
do Python em seu código - Como anexar e remover itens eficientemente de ambos os extremos de um
deque
- Como usar
deque
para construir filas e pilhas eficientes - Quando vale a pena usar o
deque
em vez dalista
Finalmente, você escreverá alguns exemplos que mostram alguns casos de uso comuns do deque
, que é um dos tipos de dados mais poderosos do Python.
Começando com o deque
do Python
Anexar itens ao final e removê-los é uma operação normalmente eficiente em uma lista do Python. Se usarmos a notação Big O para complexidade de tempo, podemos dizer que essas operações são O (1). No entanto, quando o Python precisa realocar memória para aumentar a lista subjacente para aceitar novos itens, essas operações ficam mais lentas e podem se tornar O (n).
Além disso, anexar e remover itens no início de uma lista do Python são conhecidos por serem operações ineficientes com velocidade O (n).
O deque
é uma fila bidirecional e oferece desempenho próximo de O (1) tanto para anexar quanto para remover itens de ambos os extremos. Isso ocorre porque o deque
é implementado como uma lista vinculada internamente. Em vez de realocar memória quando a lista subjacente está cheia, o deque
aloca novos blocos de memória em vez disso, mantendo assim as operações de inserção e remoção rápidas.
O módulo collections
é parte da biblioteca padrão do Python. Portanto, não é necessário instalar nada adicional para usar o deque
em seus projetos.
Para começar a usar o deque
, você precisa importar o módulo collections
e, em seguida, criar uma instância do deque
, como mostrado no exemplo a seguir:
Agora você está pronto para usar o deque
em seu código. Vamos explorar suas características e funcionalidades mais a fundo.
Anexando e Removendo Itens Eficientemente
Os dois principais métodos que você usará com o deque
são .append()
e .pop()
, que funcionam da mesma forma que os métodos correspondentes de uma lista do Python.
O método .append()
é usado para anexar um item ao final do deque
. Por exemplo:
Da mesma forma, o método .pop()
é usado para remover o último item do deque
e retorná-lo. Se você não passar nenhum índice como argumento, o .pop()
remove o último item:
Você também pode passar um índice para o .pop()
para remover um item específico do deque
:
Lembre-se de que quando você remove um item do deque
usando o .pop()
, ele é removido da extremidade oposta à que você está anexando itens. Isso ocorre porque o deque
é uma fila bidirecional, ou seja, você pode anexar e remover itens de ambos os extremos da fila.
O deque
também permite anexar e remover itens no início da fila de maneira eficiente, usando os métodos .appendleft()
e .popleft()
, respectivamente. Por exemplo:
Esses métodos funcionam da mesma forma que o .append()
e o .pop()
, mas utilizam a extremidade oposta do deque
.
Vamos ver um exemplo completo para entender melhor como usar o deque
:
A saída será:
Como você pode ver, o deque
mantém a ordem dos itens corretamente e os métodos .append()
, .pop()
, .appendleft()
e .popleft()
funcionaram corretamente.
Acessando Itens Aleatórios em um deque
Além de anexar e remover itens de ambos os sentidos do deque
, você também pode acessar itens específicos de maneira eficiente, da mesma forma que faria com uma lista do Python.
Como o deque
é implementado como uma lista vinculada internamente, o acesso aos itens no deque
é uma operação de tempo constante O (1), independentemente do índice do item que você está acessando.
Para acessar um item em um deque
, você pode usar a mesma sintaxe que usaria para acessar um item em uma lista:
Onde index
é a posição do item que você deseja acessar. Lembre-se de que a primeira posição é 0.
Se você tentar acessar um item fora dos limites do deque
, ou seja, usando um índice maior ou igual ao tamanho do deque
, uma exceção IndexError
será levantada.
Se você quiser acessar o primeiro item sem removê-lo do deque
, pode usar o atributo .peek()
:
Esse método é útil quando você deseja apenas verificar um item no início da fila sem removê-lo do deque
.
Vamos ver um exemplo completo para entender melhor como acessar itens em um deque
:
A execução desse código elevará uma exceção IndexError
, porque estamos tentando acessar um item fora dos limites do deque
.
Construindo Filas e Pilhas Eficientes com o deque
Uma das principais razões para usar o deque
em vez de uma lista do Python é a eficiência ao construir filas e pilhas. O deque
permite anexar e remover itens rapidamente de ambos os extremos da fila, sem realocar memória.
Para construir uma fila eficiente com o deque
, você usaria os métodos .append()
e .popleft()
. Por exemplo:
Aqui, você está usando o .append()
para adicionar itens no final da fila e o .popleft()
para remover itens do início da fila. Esses métodos são muito rápidos e eficientes porque o deque
é implementado como uma lista vinculada internamente.
Da mesma forma, para construir uma pilha eficiente com o deque
, você usaria os métodos .append()
e .pop()
. Por exemplo:
Aqui, você está usando o .append()
para adicionar itens no final da pilha e o .pop()
para remover itens do final da pilha. Mais uma vez, esses métodos são muito rápidos e eficientes graças à implementação do deque
como uma lista vinculada.
Explorando Outras Funcionalidades do deque
Além das funcionalidades básicas de adicionar e remover itens, o deque
também oferece outras funcionalidades importantes que podem ser úteis em diferentes situações. Vamos dar uma olhada em algumas delas:
Limitando o Número Máximo de Itens: .maxlen
Ao criar um deque
, você pode especificar um número máximo de itens que ele pode conter usando o argumento maxlen
. Se você definir um valor para maxlen
, o deque
rejeitará automaticamente os itens mais antigos quando atingir o limite especificado. Por exemplo:
A saída será:
Neste exemplo, o deque
foi definido com uma capacidade máxima de 3 itens usando o argumento maxlen
. Quando o quarto item é adicionado, o deque
automaticamente descarta o item mais antigo e mantém apenas os últimos 3 itens.
Essa funcionalidade é útil quando você precisa manter um histórico limitado de itens ou quando deseja definir um tamanho máximo fixo para uma fila ou pilha.
Girando os Itens: .rotate()
Outra funcionalidade interessante oferecida pelo deque
é a capacidade de girar os itens em torno do deque
em uma determinada quantidade de posições. Isso pode ser útil em situações em que você precisa deslocar os itens em uma fila ou uma pilha.
O método .rotate()
aceita um argumento opcional que especifica o número de posições para girar os itens. Se o argumento for positivo, os itens serão girados para a direita, enquanto se for negativo, os itens serão girados para a esquerda. Por exemplo:
A saída será:
Neste exemplo, você cria um deque
com alguns itens e, em seguida, usa o método .rotate()
para girar os itens. Note que se você usar um argumento maior do que o tamanho do deque
, ele irá ajustá-lo automaticamente para evitar erros.
Adicionando Vários Itens de Uma Vez: .extendleft()
Além de adicionar um item por vez usando o método .append()
ou .appendleft()
, você também pode adicionar vários itens de uma vez ao deque
usando o método .extendleft()
. Esse método aceita um iterável como argumento e adiciona cada item no iterável ao início do deque
na ordem em que estão. Por exemplo:
A saída será:
Ao usar o .extendleft()
, é importante observar que a ordem dos itens no iterável é preservada ao serem adicionados ao deque
. Isso significa que o último item do iterável será o primeiro item no deque
.
Usando as Funcionalidades de Lista do Python no deque
Embora o deque
seja uma fila bidirecional e ofereça funcionalidades especiais para adicionar e remover itens de seus dois extremos, ele também pode ser usado como uma lista normal do Python quando necessário.
O deque
herda todas as funcionalidades de lista do Python, como len()
, in
e slicing
. Isso permite que você use o deque
como uma lista completa quando necessário.
Por exemplo, você pode verificar o tamanho de um deque
usando a função len()
:
Da mesma forma, você também pode verificar se um item está presente em um deque
usando o operador in
:
Você também pode usar a sintaxe de fatiamento (slicing
) para acessar uma parte específica do deque
:
Essas funcionalidades permitem que você use o deque
como uma lista completa quando necessário, aproveitando suas vantagens de desempenho ao mesmo tempo que se beneficia das funcionalidades da lista.
Colocando o deque
do Python em Ação
Agora que você entende os conceitos fundamentais do deque
e como usá-lo, vamos explorar algumas situações comuns em que o deque
pode ser útil.
Mantendo um Histórico de Páginas
Suponha que você esteja desenvolvendo um navegador web e precisa manter um histórico das páginas visitadas pelo usuário. O deque
é perfeito para essa situação, pois permite adicionar as páginas visitadas ao final do deque
e remover as páginas mais antigas quando o limite especificado for atingido.
A saída será:
Neste exemplo, você cria um deque
com uma capacidade máxima de 10 itens, simulando o histórico de páginas visitadas pelo usuário. À medida que o usuário visita novas páginas, elas são adicionadas ao final do deque
. Quando o deque
atinge o limite de 10 itens, as páginas mais antigas são automaticamente removidas.
Compartilhando Dados Entre Threads
Se você estiver trabalhando com programação multithread em Python e precisar compartilhar dados entre diferentes threads, o deque
é uma ótima opção, pois é seguro para uso simultâneo por várias threads.
O deque
fornece operações atômicas para adicionar e remover itens sem a preocupação de conflitos de acesso simultâneo entre as threads. Isso o torna uma escolha adequada para implementar buffers entre threads produtoras e consumidores.
Vejamos um exemplo simples em que duas threads compartilham um deque
para adicionar e remover itens:
Neste exemplo, você cria um deque
como um buffer compartilhado entre duas threads. A função producer()
adiciona itens ao buffer usando o .append()
, enquanto a função consumer()
remove itens do buffer usando o .popleft()
.
O uso do deque
garante que as operações de adição e remoção sejam atomicamente seguras entre as threads e evita possíveis conflitos de acesso simultâneo.
Emulando o Comando tail
Suponha que você precise implementar a funcionalidade do comando tail
do Linux, que permite visualizar as últimas linhas de um arquivo em tempo real. O deque
pode ser útil para essa tarefa, pois permite manter uma “janela deslizante” de tamanho fixo das linhas lidas.
Neste exemplo, você cria um deque
vazio com uma capacidade máxima igual ao tamanho da “janela deslizante”. Em seguida, lê as linhas de um arquivo e as adiciona ao final do deque
.
Ao final, você itera sobre as linhas armazenadas no deque
e as imprime.
O deque
garante que apenas as últimas linhas lidas sejam armazenadas no buffer. Quando um novo item é adicionado, o item mais antigo é automaticamente descartado, mantendo assim uma janela deslizante das últimas linhas.
Conclusão
Neste tutorial, você aprendeu a usar o deque
do Python para implementar filas e pilhas eficientes. O deque
oferece vantagens de desempenho ao anexar e remover itens de seus dois extremos, tornando-o ideal para construir pipelines de dados eficientes em Python.
Você aprendeu como anexar e remover itens do deque
eficientemente, tanto no início quanto no final da fila. Também exploramos outras funcionalidades importantes, como limitar o número máximo de itens, girar os itens e adicionar vários itens de uma vez.
Além disso, você aprendeu como usar o deque
para manter um histórico de páginas visitadas, compartilhar dados entre threads e emular a funcionalidade do comando tail
do Linux.
Lembre-se de que, embora o deque
possa ser usado como uma lista completa e ofereça funcionalidades semelhantes às listas do Python, é projetado principalmente para otimizar operações de anexar e remover itens de ambos os extremos.
Agora você pode aproveitar ao máximo o deque
do Python e implementar filas e pilhas eficientes em seus projetos!