Pular para o conteúdo

Como Usar o OrderedDict no Python?

[

OrderedDict vs dict em Python: A ferramenta certa para o trabalho

Às vezes, você precisa de um dicionário em Python que lembre a ordem dos seus itens. No passado, existia apenas uma ferramenta para resolver esse problema específico: a classe OrderedDict do Python. É uma subclasse de dicionário especialmente projetada para lembrar a ordem dos itens, que é definida pela ordem de inserção das chaves.

Isso mudou no Python 3.6. A classe embutida dict agora também mantém seus itens ordenados. Por causa disso, muitos na comunidade Python se perguntam se o OrderedDict ainda é útil. Uma análise mais detalhada do OrderedDict revelará que essa classe ainda oferece recursos valiosos.

Neste tutorial, você aprenderá como:

  • Criar e usar objetos OrderedDict em seu código
  • Identificar as diferenças entre OrderedDict e dict
  • Compreender os prós e contras de usar OrderedDict vs dict

Com esse conhecimento, você será capaz de escolher a classe de dicionário que melhor atenda às suas necessidades quando desejar preservar a ordem dos itens.

No final do tutorial, você verá um exemplo de implementação de uma fila baseada em dicionário usando OrderedDict, o que seria mais desafiador se você usasse um objeto dict regular.

Escolhendo entre OrderedDict e dict

Por anos, os dicionários em Python eram estruturas de dados não ordenadas. Os desenvolvedores em Python estavam acostumados com esse fato e contavam com listas ou outras sequências quando precisavam manter seus dados em ordem. Com o tempo, os desenvolvedores sentiram a necessidade de um novo tipo de dicionário, um que mantivesse seus itens ordenados.

Lá em 2008, o PEP 372 introduziu a ideia de adicionar uma nova classe de dicionário ao módulo collections. Seu objetivo principal era lembrar a ordem dos itens conforme definida pela ordem de inserção das chaves. Assim surgiu o OrderedDict.

Os desenvolvedores principais do Python queriam preencher essa lacuna e fornecer um dicionário que pudesse preservar a ordem das chaves inseridas. Isso, por sua vez, permitiu uma implementação mais simples e direta.

É importante lembrar que a partir do Python 3.7, a classe dict também passou a manter a ordem dos itens, tornando a escolha entre OrderedDict e dict mais uma questão de preferência ou compatibilidade com versões mais antigas do Python.

Começando com o OrderedDict do Python

Criando objetos OrderedDict

A criação de objetos OrderedDict é bastante simples. Você pode usar a sintaxe do dicionário padrão do Python, mas em vez de usar {}, você usará a função OrderedDict() do módulo collections. Veja o exemplo abaixo:

from collections import OrderedDict
# Criando um objeto OrderedDict vazio
od = OrderedDict()
# Criando um OrderedDict com itens
od = OrderedDict([('chave1', 'valor1'), ('chave2', 'valor2'), ('chave3', 'valor3')])

Gerenciando itens em um OrderedDict

Para gerenciar os itens em um OrderedDict, você pode usar métodos semelhantes aos do dicionário padrão do Python, como __setitem__(), __getitem__(), __delitem__(), entre outros. Além disso, o OrderedDict também possui métodos específicos para gerenciar a ordem dos itens, como move_to_end() e popitem(). Veja o exemplo abaixo:

from collections import OrderedDict
od = OrderedDict([('chave1', 'valor1'), ('chave2', 'valor2'), ('chave3', 'valor3')])
# Obtendo o valor de uma chave
valor = od['chave2']
print(valor) # Output: valor2
# Movendo um item para o final do OrderedDict
od.move_to_end('chave1')
print(od) # Output: OrderedDict([('chave2', 'valor2'), ('chave3', 'valor3'), ('chave1', 'valor1')])
# Removendo e retornando o último item do OrderedDict
item_removido = od.popitem()
print(item_removido) # Output: ('chave1', 'valor1')

Iterando sobre um OrderedDict

Assim como em um dicionário padrão, você pode iterar sobre um OrderedDict usando um loop for. A diferença é que a ordem dos itens no OrderedDict será mantida durante a iteração. Veja o exemplo abaixo:

from collections import OrderedDict
od = OrderedDict([('chave1', 'valor1'), ('chave2', 'valor2'), ('chave3', 'valor3')])
# Iterando sobre as chaves e valores do OrderedDict
for chave, valor in od.items():
print(chave, valor)
# Output:
# chave1 valor1
# chave2 valor2
# chave3 valor3

Iterando em ordem reversa com reversed()

Você também pode iterar sobre um OrderedDict em ordem reversa usando a função reversed(). Veja o exemplo abaixo:

from collections import OrderedDict
od = OrderedDict([('chave1', 'valor1'), ('chave2', 'valor2'), ('chave3', 'valor3')])
# Iterando em ordem reversa
for chave, valor in reversed(od.items()):
print(chave, valor)
# Output:
# chave3 valor3
# chave2 valor2
# chave1 valor1

Esses são apenas alguns exemplos de como criar e gerenciar objetos OrderedDict. A biblioteca collections oferece muito mais recursos que podem ser úteis em situações específicas.

Explorando recursos exclusivos do OrderedDict do Python

O OrderedDict do Python possui recursos exclusivos que podem ser úteis em determinados cenários. Alguns desses recursos incluem:

Reordenando itens com .move_to_end()

O método .move_to_end() permite reordenar um item específico para o final do OrderedDict. Isso pode ser útil se você precisar modificar a ordem de prioridade de um item. Veja o exemplo abaixo:

from collections import OrderedDict
od = OrderedDict([('A', 1), ('B', 2), ('C', 3)])
# Reordenando o item 'B' para o final do OrderedDict
od.move_to_end('B')
print(od) # Output: OrderedDict([('A', 1), ('C', 3), ('B', 2)])

Removendo itens com .popitem()

O método .popitem() remove e retorna o último item inserido no OrderedDict. Isso pode ser útil se você precisar remover o item mais recente ou iterar e remover itens em ordem reversa. Veja o exemplo abaixo:

from collections import OrderedDict
od = OrderedDict([('A', 1), ('B', 2), ('C', 3)])
# Removendo e retornando o último item do OrderedDict
item_removido = od.popitem()
print(item_removido) # Output: ('C', 3)

Testando igualdade entre dicionários

O OrderedDict permite testar a igualdade entre dicionários de forma sensível à ordem dos itens. Isso significa que dois OrderedDict serão considerados iguais apenas se tiverem a mesma ordem de inserção dos itens. Veja o exemplo abaixo:

from collections import OrderedDict
od1 = OrderedDict([('A', 1), ('B', 2), ('C', 3)])
od2 = OrderedDict([('B', 2), ('C', 3), ('A', 1)])
print(od1 == od2) # Output: False

Adicionando novos atributos a uma instância de dicionário

Uma vantagem do OrderedDict é que você pode adicionar novos atributos diretamente à instância do dicionário. Essa é uma funcionalidade exclusiva do OrderedDict e não está presente no dict padrão. Veja o exemplo abaixo:

from collections import OrderedDict
od = OrderedDict([('A', 1), ('B', 2), ('C', 3)])
# Adicionando um novo atributo à instância do OrderedDict
od.novo_atributo = 'valor'
print(od.novo_atributo) # Output: valor

Esses são apenas alguns exemplos dos recursos exclusivos do OrderedDict. Existem muitas outras funcionalidades que podem ser exploradas dependendo das suas necessidades.

Mesclando e atualizando dicionários com operadores

No Python, você pode mesclar e atualizar dicionários usando os operadores + e |. Esses operadores também funcionam com OrderedDict. Veja o exemplo abaixo:

from collections import OrderedDict
od1 = OrderedDict([('A', 1), ('B', 2)])
od2 = OrderedDict([('C', 3), ('D', 4)])
od3 = od1 + od2
print(od3) # Output: OrderedDict([('A', 1), ('B', 2), ('C', 3), ('D', 4)])

Nesse exemplo, os dicionários od1 e od2 são mesclados por meio do operador +, criando um novo OrderedDict chamado od3 com todos os itens dos dicionários originais.

Você também pode atualizar um OrderedDict existente com os itens de outro OrderedDict usando o operador |. Veja o exemplo abaixo:

from collections import OrderedDict
od1 = OrderedDict([('A', 1), ('B', 2)])
od2 = OrderedDict([('C', 3), ('D', 4)])
od1 |= od2
print(od1) # Output: OrderedDict([('A', 1), ('B', 2), ('C', 3), ('D', 4)])

Nesse exemplo, o OrderedDict od1 é atualizado com os itens do OrderedDict od2 por meio do operador |.

Considerando o desempenho

Ao escolher entre OrderedDict e dict, é importante considerar o desempenho. O OrderedDict tem uma leve desvantagem em termos de velocidade de acesso, ocupando mais memória por causa das listas extras necessárias para rastrear a ordem dos itens. No entanto, para um número razoável de itens, a diferença de desempenho será insignificante na maioria dos casos.

Se a performance for uma preocupação crítica, o dict é geralmente mais rápido para a maioria das operações, pois não precisa manter a ordem dos itens. No entanto, ao lidar com aplicativos em que a ordem dos itens é importante, como a renderização de templates HTML, a geração de JSON ou a construção de URLs, o OrderedDict pode ser a escolha certa para garantir a integridade da ordem dos itens.

Escolhendo o dicionário certo para o trabalho

Ao decidir entre OrderedDict e dict, leve em consideração os seguintes pontos:

  • Se você precisa que a ordem dos itens seja explicitamente preservada, o OrderedDict é a opção correta. Isso é especialmente relevante em versões mais antigas do Python antes da 3.7.
  • Se você está atualizado para o Python 3.7 ou superior e não tem exigências específicas em relação à ordem dos itens, o dict padrão será suficiente e pode ter melhor desempenho em certos casos.

Construindo uma fila baseada em dicionário

Para ilustrar uma aplicação prática do OrderedDict, vamos implementar uma fila baseada em dicionário usando o OrderedDict. Nesse exemplo, vamos criar uma fila que mantenha a ordem de chegada dos elementos.

from collections import OrderedDict
class Fila:
def __init__(self):
self._fila = OrderedDict()
def enfileirar(self, elemento):
self._fila[elemento] = None
def desenfileirar(self):
return self._fila.popitem(last=False)[0]
def tamanho(self):
return len(self._fila)
def __str__(self):
return f"Fila({list(self._fila.keys())})"

Nesse exemplo, a classe Fila utiliza o OrderedDict para manter a ordem de chegada dos elementos. O método enfileirar() adiciona um elemento à fila, o método desenfileirar() remove e retorna o elemento na primeira posição, o método tamanho() retorna o número de elementos na fila e o método __str__() retorna a representação da fila em formato de string.

Aqui está um exemplo de uso dessa fila:

fila = Fila()
fila.enfileirar("A")
fila.enfileirar("B")
fila.enfileirar("C")
print(fila) # Output: Fila(['A', 'B', 'C'])
elemento = fila.desenfileirar()
print(elemento) # Output: A
print(fila) # Output: Fila(['B', 'C'])

Com esse exemplo, mostramos como o OrderedDict pode ser útil para implementar estruturas de dados mais complexas, como uma fila.

Conclusão

O OrderedDict do Python é uma ferramenta poderosa para lidar com dicionários que precisam lembrar a ordem dos itens. Embora o dict padrão agora também mantenha a ordem dos itens a partir do Python 3.7, o OrderedDict ainda oferece recursos exclusivos e é a escolha certa quando a preservação da ordem é crucial.

Neste tutorial, você aprendeu como criar e usar OrderedDict, identificar as diferenças entre OrderedDict e dict e considerar o desempenho ao escolher entre eles. Além disso, vimos exemplos práticos de aplicação do OrderedDict e como construir uma fila baseada em dicionário.

Com essa compreensão, você pode tomar decisões informadas sobre qual classe de dicionário usar em diferentes situações, sempre levando em consideração a ordem e a eficiência do seu código Python.