dezembro 19 2016 · python · dados

Estrutura de dados em Python - Pt. 1

O Python tem uma das melhores API's para manipulação de dados que eu conheço (apesar do meu pouco conhecimento em outras linguagens, um contato apenas com Ruby e PHP). Ela fornece metodos embutidos (built-in) que fazem a maior parte do trabalho sujo em manipulação de estruturas de dados.

Nessa série de posts, trarei algumas caracteristicas das estruturas mais básicas e importantes da linguagem, além de algumas técnicas de iteração nessas mesmas estruturas.

Estrutura de dados Parte 1

Listas

As duas estruturas mais utilizadas em Python são listas e tuplas. A primeira vista, elas parecem a mesma coisa, mas não se engane. Elas possuem diferenças importantes e que podem modificar todo o comportamento do seu sistema.

Listas são indexadas a partir do zero (zeroth-index), ou seja, o seu indíce inicial é 0. Listas são estruturas mutáveis e esta é uma caracteristica muito importante. Além disso, são estruturas básicas que suportam uma gama de metódos e caracteristicas. abaixo algumas delas:

lista.append(x)

O metódo append(x) adiciona um valor ('x') ao final da lista.

>>> nova_lista = [] # Inicializa uma lista vazia;
>>> nova_lista.append('Carlos') # Adiciona a string 'Carlos' ao final da lista;
>>> nova_lista
['Carlos']

lista.extend(L)

O extend(L) adiciona todos os itens de outra lista a lista informada.

>>> nova_lista = [1, 2, 3] # Inicializa uma lista com valores;
>>> outra_lista = [4, 5, 6] # Inicializa uma nova lista com valores;
>>> nova_lista.extend(outra_lista) # 'Extende' nova_lista com os valores de outra_lista;
>>> nova_lista
[1, 2, 3, 4, 5, 6]

Um dos truques mais legais das listas é a forma fácil com a qual você pode inverter a ordem da informação contida nela. Em algumas linguagens você precisaria fazer um loop para adicionar os valores a outra lista e etc. No Python, você pode utilizar o metódo abaixo:

ATENÇÃO: Este metódo altera o valor da lista in-place, ou seja, a lista original perde seu valor inicial. Caso deseje, faça uma cópia da lista antes de utilizar o metódo.

lista.reverse()

Inverte os valores de uma lista in-place.

>>> nova_lista = [1, 2, 3]
>>> nova_lista.reverse() # Inverte a lista 'in-place'
>>> nova_lista
[6, 5, 4, 3, 2, 1]

lista.count(x)

Conta o numero de vezes que o valor 'x' aparece dentro da lista.

>>> nova_lista = list('ananindeua') # O metodo list() Cria uma lista a partir da string fornecida
['a', 'n', 'a', 'n', 'i', 'n', 'd', 'e', 'u', 'a']
>>> nova_lista.count('a')
3
>>> nova_lista.count('n')
3

list.sort(x)

Ordena o conteúdo da lista, in-place.

ATENÇÃO: Este metódo altera o valor da lista in-place, ou seja, a lista original perde seu valor inicial. Caso deseje, faça uma cópia da lista antes de utilizar o metódo.

>>> nova_lista = list('ananindeua') # O metodo list() Cria uma lista a partir da string fornecida
['a', 'n', 'a', 'n', 'i', 'n', 'd', 'e', 'u', 'a']
>>> nova_lista.sort()
['a', 'a', 'a', 'd', 'e', 'i', 'n', 'n', 'n', 'u']

lista.insert(i, x)

Adiciona um item 'x' no indice 'i' da lista. Lembre-se que a lista é uma estrutura que é indexada por 0, ou seja, o 0 é o primeiro valor da lista.

>>> nova_lista = 'I love Python'.split(' ') # Cria uma lista a partir de uma string, separando os valores nos espaços.
['I', 'love', 'Python']
>>> nova_lista.insert(0, 'You')
['You', 'I', 'love', 'Python']

Se você adicionar um valor maior que o último indíce da lista, o valor será adicionado ao final da lista.

lista.remove(x)

Remove o primeiro valor da lista cujo valor seja 'x'. Retorna um erro caso o valor não exista.

>>> nova_lista = 'I love Python'.split(' ') # Cria uma lista a partir de uma string, separando os valores nos espaços.
['I', 'love', 'Python']
>>> nova_lista.remove('Python')
['I', 'love']
>>> nova_lista.remove('Ruby') # Levanta um erro!
ValueError: list.remove(x): x not in list # Valor 'x' não está na lista.

Você pode utilizar uma lista como uma pilha, seguindo o conceito de LIFO (Last In First Out), com os metodos append(x) (visto acima) e pop(x) abaixo.

lista.pop([i])

Remove e retorna um item de uma determinada posição, caso não seja especificado nenhum item, remove e retorna o elemento na última posição (First Out) da lista. Note que o parametro i entre colchetes quer dizer opcional, não que você deva colocar colchetes na posição.

>>> nova_lista = 'I Love Python'.split(' ')
['I', 'love', 'Python']
>>> removido = nova_lista.pop() # Remove e retorna o ultimo item;
'Python'
>>> nova_lista
['I', 'Love']

List slicing (Fatiamento de listas)

Além de todos os metódos acima, as listas suportam slicing, fatiamento de listas. A construção do slicing para listas é a mesma para strings.

A sintaxe da fatia é a seguinte lista[start:end:stride] onde start é o indice inicial, end o indice final e stride é o 'pulo' de indice. start é inclusivo e end é 'exclusivo', ou seja o valor no indice final não está incluso no retorno da fatia.

Fatias retornam novas listas de valores e não alteram o valor inicial da lista.

>>> nova_lista = 'Python is a beautiful programming language'.split(' ')
['Python', 'is', 'a', 'beautiful', 'programming', 'language']
>>> nova_lista[0:2] # Retorne os valores do index 0 até o indice 2
['Python', 'is'] # O indice 2 ('a') é exclusivo, por isso não está no retorno
>>> nova_lista[3:5] # A partir do indice 3 (inclusivo) até o indice 5 (exclusivo)
['beautiful', 'programming']
>>> nova_lista[3:] # Você pode omitir o indice final para considerar: 'Toda a lista a partir do indice 3'
['beautiful', 'programming', 'language']
>>> nova_lista[::-1] # Hack importante! Você pode inverter os valores da lista passando um indice negativo no parametro 'stride';
['language', 'programming', 'beautiful', 'a', 'is', 'Python']
>>> nova_lista[-2:] # Passar indices negativos no parametro 'start' fatia a lista de trás pra frente;
['programming', 'language']

Pelo fato do Python ter valores passados por referência, tentar copiar uma lista da maneira padrão pode causar alguns problemas:

>>> nova_lista = [1, 2, 3, 4, 5]
>>> lista_copiada = nova_lista
>>> lista_copiada.append(6)
>>> lista_copiada
[1, 2, 3, 4, 5, 6]
>>> nova_lista
[1, 2, 3, 4, 5, 6]

WHAT!? O que diabos aconteceu? Simples, lembra da passagem por referência ? É exatamente isso que aconteceu. As duas variaveis apontam para o mesmo caminho na memória do computador. Isso pode ser verificado facilmente com:

>>> lista_copiada is nova_lista # Você pode comparar as duas listas;
True
>>> id(nova_lista) # Ou pode utilizar o metodo 'id()', que retorna o endereço na memória do objeto 
140252627427208
>>> id(lista_copiada)
140252627427208

Se você desejar copiar uma lista para outra, a forma mais fácil de fazer isso é com list slicing, desta forma:

>>> lista_copiada = nova_lista[:]
>>> lista_copiada.append(7)
[1, 2, 3, 4, 5, 6, 7]
>>> nova_lista
[1, 2, 3, 4, 5, 6]
>>> lista_copiada is nova_lista
False
>>> id(lista_copiada)
140252627588552
>>> id(nova_lista)
140252627427208

Considerações finais

Como vimos aqui, as listas são estruturas poderosas e fáceis de trabalhar, mas como já dizia o falecido Uncle Ben (de Spider Man, não Uncle Bob do Clean Code): "Com grandes poderes, vêm grandes responsabilidades".

Tenha cuidado com a maleabilidade das listas em seus programas, ou você poderá ter resultados inesperados.

No próximo post, falaremos sobre as primas das listas, as Tuplas

Até mais pessoal e Keep Coding!

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket