Prévia do material em texto
PROGRAMAÇÃO
BACK END I
Pedro Henrique Chagas Freitas
Módulo collections
em Python
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Reconhecer high-performance container datatypes.
� Listar as principais collections.
� Programar usando collections.
Introdução
Neste capítulo, iremos abordar os conceitos de high performance container
datatypes. Além disso, listaremos as principais collections Python e
apresentaremos um exemplo utilizando collections da linguagem
Python.
High performance container datatypes
em Python
Para compreender a estrutura da linguagem Python, em especial suas coleções
(collections), utilizaremos como principal fonte o repositório de disse-
minação oficial da linguagem Python, o https://python.org. Veja as principais
características da linguagem Python a seguir:
� alto nível de automação de scripts;
� interpretada;
� imperativa;
� multiparadigma;
� tipagem forte e dinâmica.
Dentre as características citadas, duas em especial serão objeto de estudo
deste capítulo, quando tratarmos de high performance container datatypes em
Python. A primeira é o alto nível de automação de scripts, ou seja, Python é
uma linguagem de alto nível, próxima à interpretação da linguagem humana,
e isso é uma das principais qualidades da linguagem Python. Além disso,
Python é uma linguagem interpretada, portanto, o código-fonte de um
programa ou script em Python é analisado primeiro por um interpretador e,
em seguida, executado pelo processador (TOUSIG, 2008).
Isso é importante, pois foi exatamente isso que abriu caminho para a
programação modular de Python que, por sua vez, deu origem aos módulos
de contêiner de tipos de dados Python de alta performance (high performance
container datatypes). Os tipos de dados nativos de Python pertencem à ca-
tegoria coleções (collections), e são: os conjuntos ou sets, que utilizam
chaves, { e }; as listas, que utilizam colchetes, [ e ]; e as tuplas, que utilizam
parênteses, ( e ).
Isto é fundamental para compreendermos a programação modular, que
implementa os módulos de contêiner de tipos de dados Python de alta per-
formance. Para sua criação, precisamos dividir tarefas grandes em subtarefas
de menor complexidade. Isto é feito por meio de módulos, que são menores e
mais gerenciáveis, o que auxilia na performance desejada. Ao ser agrupados,
criam tarefas maiores que podem ou não ser agrupadas em contêineres Python
(SOMMERVILLE, 2008).
Estes contêineres, por sua vez, conterão os tipos de dados (datatypes)
citados: conjuntos ou sets, listas e tuplas. Dessa forma, o suporte de Python
à programação modular é o que viabiliza a implementação de contêineres de
alta performance nesta linguagem. Os módulos são como “tijolos”, divididos
para aumentar a performance dos contêineres, que são a junção das tarefas
menores em maiores, para aumento da performance na automação de scripts
de tarefas (PRESSMAN, 2011).
Existem diversos tipos de contêineres nativos de Python de alta performance
que realizam modularização. Entre eles, os principais e mais conhecidos para
a implementação de alto desempenho são queue, stack, deque, dict e
OrderedDict.
A Figura 1 mostra um exemplo de simulação de tráfego de pacotes mo-
dularizados com métodos (set e get) com o contêiner OrderedDict em
milésimos de segundos.
Módulo collections em Python2
Figura 1. Representação do fluxo de tráfego de dados com envio e recebimento de dados
por meio dos métodos set e get em milésimos de segundo, por uma collection
com contêiner OrderedDict.
Fonte: Lai e Mazzoleni ([201-?], documento on-line).
Principais collections da linguagem Python
Existem diversos tipos de collections em Python e selecionamos qua-
tro destas, que são comumente utilizadas. As collections são módulos
de classes abstratas da linguagem Python que estão reunidas na biblioteca
collections. O objetivo dessa biblioteca é reunir tipos alternativos de
dados, além das estruturas de filas, listas, conjuntos (sets), conforme vimos
anteriormente. A ideia da criação da biblioteca collections é reunir tipos
de dados, além dos tipos nativos da linguagem Python (PRESSMAN, 2011).
Esses novos tipos de dados reunidos na biblioteca collections provêm
novas funcionalidades e tipos de dados alternativos, que podem ser utilizados
em diversos cenários. Logo, dependendo do tipo de projeto, temos collec-
tions especificas que podem ser empregadas. Dentre essas, as principais
são: defaultdict, Counter, deque e namedtuple.
Ao contrário de um dicionário normal (dict) a collections de-
faultdict não pressupõe a necessidade de se verificar se uma chave está
presente ou não. Veja o exemplo a seguir.
3Módulo collections em Python
from collections import defaultdict
cores = [('1', 'azul'), ('2', 'amarelo'), ('3', 'vermelho'), ('1',
'branco'), ('3', 'verde')]
cores _ favoritas = defaultdict(list)
for chave, valor in cores:
cores _ favoritas[chave].append(valor)
print(cores _ favoritas)
Neste caso, vamos gerar a saída a seguir.
defaultdict(<class 'list'>, {'1': ['azul', 'branco'], '2': ['ama-
relo'], '3': ['vermelho', 'verde']})
Já a coleção counter implementa um contador e permite que seja rea-
lizada a contagem de ocorrência de um determinado item em uma estrutura
de dados, como no exemplo a seguir.
from collections import Counter
cores = ['amarelo', 'azul', 'azul', 'vermelho', 'azul', 'verde',
'vermelho']
contador = Counter(cores)
print(contador)
Como saída, teremos:
Counter({'azul': 3, 'vermelho': 2, 'amarelo': 1, 'verde': 1})
Por sua vez, a coleção deque é uma estrutura que disponibiliza uma fila
com duas extremidades, com possibilidade de remover e adicionar elementos
dos dois lados, como no exemplo a seguir.
from collections import deque
fila = deque()
fila.append('1')
fila.append('2')
fila.append('3')
print(len(fila)) #saída: 3
fila.pop() #exclui elemento da direita
fila.append('3') #adiciona elemento na direita
Módulo collections em Python4
fila.popleft() #exclui elemento da esquerda
fila.appendleft('1') #adiciona elemento na esquerda
A namedtuple é uma coleção que faz a nomeação de duas tuplas. Ela
faz com que não seja necessário adicionar índices inteiros para acessar os
elementos das tuplas. Logo, podemos utilizar strings, da mesma forma como
em um dicionário, mas o namedtuple é imutável: uma vez adicionado, não
pode ser alterado. Veja o exemplo a seguir.
from collections import namedtuple
Conta = namedtuple('Conta', 'numero titular saldo limite')
conta = Conta('123-4', 'João', 1000.0, 1000.0)
print(conta)
# saída: Conta(numero='123-4', titular='João', saldo=1000.0,
limite=1000.0)
print(conta.titular) #saída: João
No caso específico da coleção namedtuple, teremos dois argumentos
obrigatórios, que serão o nome da tupla e seus campos separados por vírgula
e espaço.
Desenvolvendo com collections Python
Utilizaremos a coleção deque a fim de implementar uma fila, que retornará
dados da esquerda para a direita. As coleções deque são generalizações
de pilhas e filas. O tipo deque suporta acréscimos e pops eficientes em
termos de memória e são seguros de ambos os lados do deque (esquerda e
direita), com aproximadamente o mesmo desempenho em qualquer direção.
Por esta razão, o deque também é utilizado para a implementação de alto
desempenho em contêineres Python, conforme mencionamos no início deste
capítulo (TONSIG, 2008).
A coleção deque costuma ter comprimento limitado, logo, pode ser uti-
lizada para rastrear transações e conjuntos de dados. Esta coleção possui
suporte para os seguintes métodos, apresentados no Quadro 1.
5Módulo collections em Python
Método Resultado da execução
append(x) Adicione x ao lado direito do deque.
appendleft(x) Adicione x ao lado esquerdo do deque.
clear() Remova todos os elementos do deque,
deixando-o com comprimento 0.
copy() Crie uma cópia superficial do deque.
count(x) Conteo número de elementos
deque iguais a x.
extend(iterável) Estenda o lado direito do deque,
acrescentando elementos do
argumento iterável.
extendleft(iterável) Estenda o lado esquerdo do deque, anexando
elementos de iterável. Observe que a série da
esquerda anexa resulta na reversão da ordem
dos elementos no argumento iterável.
index(x[, ini-
cio[, fim]])
Retorne a posição de x no deque (ou dentro
do intervalo definido por inicio e fim).
Retorna a primeira correspondência ou gera
um ValueError se não for encontrado.
insert(i, x) Insira x no deque na posição i. Se a inserção
fizer com que um deque limitado cresça além
de maxlen, um IndexError será gerado.
pop() Remova e retorne um elemento do lado
direito do deque. Se nenhum elemento
estiver presente, gera um IndexError.
popleft() Remova e retorne um elemento do lado
esquerdo do deque. Se nenhum elemento
estiver presente, gera um IndexError.
remove(valor) Remova a primeira ocorrência de valor. Se
não for encontrado, gera um ValueError.
reverse() Inverta os elementos do deque no
local e, em seguida, retorne None.
Quadro 1. Métodos suportados por objetos da classe deque
(Continua)
Módulo collections em Python6
Fonte: Collections... (2019, documento on-line).
Quadro 1. Métodos suportados por objetos da classe deque
Método Resultado da execução
rotate(n = 1) Gire o deque n passos para a direita. Se
n for negativo, gire para a esquerda.
maxlen Tamanho máximo de um deque,
ou None se for ilimitado. Este é
um atributo somente-leitura.
(Continuação)
A seguir, veja a implementação da nossa fila com a coleção deque.
>>> from collections import deque
>>> d = deque('ghi') # Cria um que com 3 itens
>>> for elem in d: # Cria regra sob o deque
... print(elem.upper())
G
H
I
>>> d.append('j') # adiciona a direita
>>> d.appendleft('f') # adiciona a esquerda
>>> d # mostra o deque
deque(['f', 'g', 'h', 'i', 'j'])
>>> d.pop() # retorna e remove do
lado direito
'j'
>>> d.popleft() # retorna e remove do
lado esquerdo
'f'
>>> list(d) # lista o conteúdo
['g', 'h', 'i']
>>> d[0] # empurra o item mais a
esquerda
'g'
7Módulo collections em Python
>>> d[-1] # empurra o item mais a
direita
'i'
>>> list(reversed(d)) # lista o conteúdo do
deque ao contrário
['i', 'h', 'g']
>>> 'h' in d # procura no deque
True
>>> d.extend('jkl') # adiciona elementos a
partir dos que já estão no deque
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> d.rotate(1) # faz a rotação pela direita
>>> d
deque(['l', 'g', 'h', 'i', 'j', 'k'])
>>> d.rotate(-1) # faz a rotação pela esquerda
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> deque(reversed(d)) # cria um novo deque com
ordem reversa
deque(['l', 'k', 'j', 'i', 'h', 'g'])
>>> d.clear() # esvazia o deque
>>> d.pop() # impede tirar de um
deque vazio
Traceback (most recent call last):
File "<pyshell#6>", line 1, in -toplevel-
d.pop()
IndexError: pop from an empty deque
>>> d.extendleft('abc') # extendleft() reverte a
ordem de entrada do deque para abc
>>> d
deque(['c', 'b', 'a'])
Perceba que acabamos de montar uma fila que pode ter inúmeras funções,
entre elas, refletir um extrato bancário, a ordem de pagamentos de uma empresa,
as transações entre um Web service e um computador cliente e muitas outras,
o que demonstra a importância das collections para a implementação de
funcionalidades diversas por meio da linguagem Python.
Módulo collections em Python8
COLLECTIONS – High-performance container datatypes. Python Software Founda-
tion, Wilmington, 2019. Disponível em: https://docs.python.org/3/library/collections.
html#collections.deque. Acesso em: 2 nov. 2019.
LAI, R.; MAZZOLENI, A. Benchmarking ‘collections’. collections 0.23 – High Performance
Container Data Types, [S. l.], [201-?]. Disponível em: https://randy3k.github.io/collections/
articles/benchmark.html#ordereddict. Acesso em: 5 nov. 2019.
PRESSMAN, R. S. Engenharia de software: uma abordagem profissional. 7. ed. Porto
Alegre: AMGH; Bookman, 2011. 780 p.
SOMMERVILLE, I. Engenharia de software. 8. ed. São Paulo: Pearson Prentice Hall, 2008.
552 p.
TONSIG, S. L. Engenharia de software: análise e projeto de sistemas. 2. ed. Rio de Janeiro:
Ciência Moderna, 2008. 319 p.
9Módulo collections em Python