Python Iluminado

Tuplas

Tuplas são uma sequência de objetos imutáveis, em outras palavras, uma vez criadas, tuplas não podem ser modificadas, normalmente são usadas para guardar dados protegidos.

As tuplas são escritas entre parênteses ().

Uma tupla em Python é semelhante a uma lista. A diferença entre os dois é que não podemos alterar os elementos de uma tupla depois de atribuída, enquanto podemos alterar os elementos de uma lista.

Criando uma Tupla

Podemos definir uma tupla da seguinte maneira:

linguagens = ("Python","Ruby","Javascript","Perl","Haskell")
print(linguagens) # ('Python', 'Ruby', 'Javascript', 'Perl', 'Haskell')

Com o método type() podemos confirmar que se trata de uma 'tuple':

type(linguagens) # <class 'tuple'>

Acessando Itens de uma Tupla

O acesso aos itens de uma tupla é idêntico ao de uma lista:

print(linguagens[0:2]) # ('Python', 'Ruby')
print(linguagens[-1]) # Haskell
print(linguagens[:-2]) # ('Python', 'Ruby', 'Javascript')
print(linguagens[:]) # ('Python', 'Ruby', 'Javascript', 'Perl', 'Haskell')

Atualizando Tuplas

Lembrando que as tuplas são imutáveis, portanto se tentarmos modificá-la, nos será retornado um erro do tipo TypeError:

linguagens[0] = "C++"
# TypeError: 'tuple' object does not support item assignment

Como já mencionado, Tuplas são imutáveis, ou seja, não podemos alterar os seus elementos, porém podemos capturar porções de uma tupla e criar novas tuplas, por exemplo:

x = (1,2)
y = (3,4)
z = x + y
print(z) # (1, 2, 3, 4)

Imprimindo Elementos de uma Tupla

As tuplas são úteis para representar o que outras linguagens costumam chamar de registros, algumas informações relacionadas que pertencem entre si, como o registro de um estudante. Não há descrição do que significa cada um desses campos, mas podemos intuir. Uma tupla nos permite “agrupar” informações relacionadas e usá-las em uma única estrutura.

estudante = ('Miguel', 29, 1990, 'Brasil')

Agora podemos utilizar um for loop para imprimir todos os elementos da tupla estudante:

for e in estudante: # Percorre os valores da tupla estudante
print(e) # Imprime os valores

Também podemos facilmente converter esta tupla em uma lista usando a técnica list comprehension:

print([e for e in estudante]) # ['Miguel', 29, 1990, 'Brasil']

Checando por Valores em uma Tupla

Assim como nas listas, também podemos checar se determinado item está presente em uma tupla:

print('Gabriel' in estudante) # False
print(1990 in estudante) # True

Além disso, podemos checar também a absência de determinado elemento:

print('Japão' not in estudante) # True
print('Brasil' not in estudante) # False

Verificando o Tamanho de uma Tupla

Para obtermos o número de itens em uma tupla, podemos usar o método len():

print(len(estudante)) # 4

Deletando a Tupla

Embora seja impossível remover itens da tupla, é possível deletá-la por completo com o uso da palavra-chave del. Observe que se tentarmos imprimir ela, ocorrerá um erro do tipo NameError, uma vez que a tupla não existe mais.

del estudante
print(estudante)
# NameError: name 'estudante' is not defined

Construtor tuple()

Somos capazes também de construir uma tupla com o uso do construtor tuple():

numeros = tuple(x for x in range(1,20,3))
print(numeros) # (1, 4, 7, 10, 13, 16, 19)

Método count()

O método count() nos retorna a quantidade de vezes que determinado valor ocorre em uma tupla

print(numeros.count(7)) # 1

Método index()

O método index() nos permite buscar por um determinado elemento e nos retorna o índice dele:

numeros.index(4) # 1

Criando uma Função que Retorna uma Tupla

Funções normalmente retornam apenas um único valor, porém ao tornarmos esse valor uma Tupla, nós podemos efetivamente agrupar a quantidade de valores que desejarmos e retorná-los juntos. Esta funcionalidade pode nos ser muito útil em casos que queiramos por exemplo encontrar a média e o desvio padrão ou talvez obter o ano, mês e dia.

Vejamos um exemplo para ilustrar esta ideia, em que vamos definir uma função de nome f que irá calcular a circunferência e a área de um círculo de raio r (o raio será informado via argumento por nós):

import math
def f(r):
""" Retorna (circunferência, área) de um círculo de raio r """
c = 2 * math.pi * r
a = math.pi * r * r
return (c, a)
print(f(5)) # (31.41592653589793, 78.53981633974483)
print(f(8)) # (50.26548245743669, 201.06192982974676)

Named Tuples

Named Tuples são objetos de fácil criação e leves. Instâncias de Named Tuples podem ser referenciadas utilizando variáveis. Elas podem serem utilizadas como uma espécie de estrutura para agruparmos dados.

É muito comum representarmos um ponto como uma tupla (x, y).

A fórmula da distância é uma expressão algébrica usada para determinar a distância entre dois pontos com as coordenadas (x1, y1) e (x2, y2).

img

from math import sqrt
p1 = (2.0, 7.0)
p2 = (2.5, 3.5)
comprimento_linha = sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)
print(comprimento_linha) # 3.5355339059327378

Ao utilizarmos uma Named Tuple, nosso código se torna mais legível, porém para usá-la devemos importá-la da biblioteca collections:

from collections import namedtuple
Ponto = namedtuple('Point', 'x y')
p1 = Ponto(1.5, 5.0)
p2 = Ponto(4.5, 1.5)
comprimento_linha = sqrt((p1.x-p2.x)**2 + (p1.y-p2.y)**2)
print(comprimento_linha) # 4.6097722286464435

Podemos usar as Named Tuples para armazenar cores RGB:

Cor = namedtuple('Cor', ['red', 'green', 'blue'])
cor = Cor(55,155,255)
print(cor) # Cor(red=55, green=155, blue=255)
print(cor.red) # 55

Tuplas vs Listas

Por que devemos usar uma Tupla ao invés de uma Lista?

  • A execução do programa é mais rápida quando manipulamos uma tupla do que uma equivalente lista.
  • As vezes desejamos que os dados não sejam modificados, se determinados que valores em uma coleção devem ser constantes no programa, utilizar uma Tupla nos protege contra acidentes de modificação.

Exemplos

Exemplo de Lista:

numeros_primos = [2, 3, 5, 7, 11, 13, 17]

Mostrando o tamanho:

print(f'# Primos: {len(numeros_primos)}')

Iterando sob a sequência:

for p in numeros_primos:
print(f'Primos: {p}')

Exemplo de Tupla:

quadrados_perfeitos = (1, 4, 9, 16, 25, 36)

Mostrando o tamanho:

print(f'# Quadrados Perfeitos: {len(quadrados_perfeitos)}')

Iterando sob a sequência:

for n in quadrados_perfeitos:
print(f'Primos: {n}')

Métodos das Listas e Tuplas

Podemos usar o método dir() para visualizarmos todos os atributos e métodos disponíveis nas listas e tuplas:

print('Métodos Lista')
print(dir(numeros_primos))
print('Métodos Tupla')
print(dir(quadrados_perfeitos))

Obtendo o Tamanho em Bytes

O método getsizeof() da biblioteca sys nos permite obter o tamanho que um objeto ocupa em bytes. Por exemplo:

import sys
lista_ex = [1, 2, 3, 'x', 'y', 'z', True, 3.14159]
tupla_ex = (1, 2, 3, 'x', 'y', 'z', True, 3.14159)
print(f'Tamanho da lista = {sys.getsizeof(lista_ex)}') # Tamanho da lista = 136
print(f'Tamanho da tupla = {sys.getsizeof(tupla_ex)}') # Tamanho da tupla = 120

Como podemos observar, a tupla ocupa menos espaço em memória que uma lista.

Comparando o Tempo

A biblioteca timeit nos fornece uma maneira simples de cronometrar pequenos trechos de código Python, podemos usá-la para medir a eficiência de estruturas de dados como listas e tuplas:

import timeit
lista_teste = timeit.timeit(stmt='[1,2,3,4,5]', number=1_000_000)
tupla_teste = timeit.timeit(stmt='(1,2,3,4,5)', number=1_000_000)
print(f'Tempo da lista: {lista_teste}') # Tempo da lista: 0.11356729100225493
print(f'Tempo da tupla: {tupla_teste}') # Tempo da tupla: 0.058329956023953855

Como podemos ver, as tuplas são uma estrutura de dados imutável e muito rápida que pode nos auxiliar bastante em nossos cálculos.