sexta-feira, 2 de novembro de 2012

O Que São Os Deques Do Python E Como Funcionam?

O Python, como as outras linguagens de programação comuns, possui os tipos de dados básicos como inteiros, floats, strings e listas. Com estes tipos básicos é possível fazer quase qualquer operação em um software. Obviamente existem outros tipos de dados que facilitam a nossa vida. Além disso sempre temos a opção de criar nossos próprios objetos para suprir necessidades específicas. Neste artigo vamos falar dos deques, que fazem parte do maravilhoso módulo collections do Python.
Deques são semelhantes às listas. A primeira diferença que se nota é que os deques podem ser definidos com um tamanho fixo, você verá que em algumas situações este recurso é bastante útil. Vamos entender melhor o seu funcionamento criando um deque vazio:

#Python 3
>>> from collections import deque
>>> md = deque(maxlen=5)
>>> md
deque([], maxlen=5)
>>> 

Caso você não defina o atributo maxlen no momento da criação do deque, o objeto não terá um número de itens limite.
Podemos inserir itens no deque da mesma forma como fazemos em listas, com o método append().
Vejamos agora o que acontece com o nosso deque quando inserimos alguns itens:

#Python 3
>>> md.append(1)
>>> md.append(2)
>>> md.append(3)
>>> md.append(4)
>>> md.append(5)
>>> md
deque([1, 2, 3, 4, 5], maxlen=5)
>>> md.append(6)
>>> md
deque([2, 3, 4, 5, 6], maxlen=5)
>>> 

No exemplo acima, inserimos cinco valores no nosso deque e ao imprimí-lo observamos que os cinco itens estão lá, da forma como foram inseridos. Observe o que ocorreu quando inserimos o sexto item.
Como o tamanho máximo da lista é 5, quando inserimos um novo item em um deque já cheio com o comando append, o valor da esquerda é removido automaticamente.
Se quisermos remover o valor da direita, podemos utilizar o comando appendleft():

#Python 3
>>> md.appendleft(7)
>>> md
deque([7, 2, 3, 4, 5], maxlen=5)
>>> 

Agora, criar uma lista vazia para populá-la posteriormente item por item pode não ser muito prático. Temos a opção de criar um deque já populado, veja o exemplo:

#Python 3
>>> lista = [1, 2, 3, 4, 5, 6]
>>> mnd = deque(lista, 5)
>>> mnd
deque([2, 3, 4, 5, 6], maxlen=5)
>>> 

Podemos criar um deque a partir de uma lista existente. Mesmo que a lista seja maior que o tamanho definido para o deque.
Para popular um deque existente a partir de uma lista devemos observar alguns detalhes:

#Python 3
>>> mnd.clear()
>>> mnd.append(lista)
>>> mnd
deque([[1, 2, 3, 4, 5, 6]], maxlen=5)
>>> mnd.clear()
>>> mnd.extend(lista)
>>> mnd
deque([2, 3, 4, 5, 6], maxlen=5)
>>>  

O comando clear() limpa o deque, deixando ele vazio novamente. Quando tentamos popular o deque com a lista pelo comando append, todos os itens da lista são inseridos no deque, ainda que o número de itens da lista seja maior que o limite do deque. Isto ocorre porque o comando append insere a lista como um único objeto. Se quisermos inserir cada item da lista separadamente devemos utilizar o comando extend() como no exemplo.
Note que podemos popular o deque da mesma forma não só com listas mas com qualquer objeto iterável (como strings, por exemplo).
Quando o objetivo é remover itens, o comportamento do deque também é semelhante ao das listas:
#Python 3
>>> mnd
deque([2, 3, 4, 5, 6], maxlen=5)
>>> mnd.pop()
6
>>> mnd
deque([2, 3, 4, 5], maxlen=5)
>>> mnd.popleft()
2
>>> mnd
deque([3, 4, 5], maxlen=5)
>>> mnd.remove(4)
>>> mnd
deque([3, 5], maxlen=5)
>>> 

Se os deques são tão semelhantes às listas, então para que eles servem afinal?
A principal vantagem dos deques se encontra no fato de você poder definir um tamanho fixo para eles e de o processo de inserção e remoção de valores ser bem prático. Desta forma, o comportamento do deque é semelhante ao de uma fila (ou queue) simplificada.
Imagine que você desenvolveu um jogo e quer armazenar uma lista das últimas 10 jogadas do jogador. Se você utilizasse uma lista normal para esta tarefa, teria que definir manualmente funções para verificar o número de jogadas e para adicionar e remover os itens na ordem certa. O deque já realiza estas tarefas naturalmente e a cada nova jogada que você insere no deque, a décima é removida.
Outra função bastante útil dos deques é o rotate():

#Python 3
>>> mnd
deque([2, 3, 4, 5, 6], maxlen=5)
>>> mnd.rotate()
>>> mnd
deque([6, 2, 3, 4, 5], maxlen=5)
>>> mnd.rotate()
>>> mnd
deque([5, 6, 2, 3, 4], maxlen=5)
>>> mnd.rotate(2)
>>> mnd
deque([3, 4, 5, 6, 2], maxlen=5)
>>> mnd.rotate(-1)
>>> mnd
deque([4, 5, 6, 2, 3], maxlen=5)
>>> 
O comando rotate, como o nome insinua, altera a posição dos itens no deque. Se não for definido nenhum argumento, o deque é rotacionado em uma posição para a direita. Argumentos com valores negativos rotacionam o deque no sentido contrário.
O rotate também possui várias utilidades. Por exemplo, imagine que o seu programa realiza uma rotina com base em um número fixo de valores, um por um. Se este procedimento for interrompido, ele deve ser retomado a partir do próximo valor fixo. Este exemplo pode ser implementado facilmente com um deque, onde o valor fixo é sempre o primeiro item e um rotate() é executado a cada fase do procedimento.
Para aprender mais sobre o deque, acesse a documentação completa do Python.

Nenhum comentário:

Postar um comentário