Tuplas vs. Listas Python: Descubra as Diferenças e Quando Usar Cada Uma!

Neste guia, você explorará as similaridades e diferenças entre tuplas e listas em Python. Além disso, entenderá as circunstâncias mais adequadas para utilizar uma tupla.

Listas e tuplas são estruturas de dados nativas em Python, ambas servindo para armazenar coleções de elementos.

Devido à sua capacidade de indexação, fatiamento e armazenamento de tipos de dados diversos, tuplas e listas podem parecer ter funcionalidades muito parecidas. Por isso, compreender as semelhanças e as distinções entre elas pode ser crucial na hora de escolher a estrutura de dados apropriada.

Vamos começar a análise!

👩🏽‍💻 Você pode acompanhar este tutorial utilizando um ambiente Python REPL ou o editor Python online do etechpt.com.

Tuplas vs Listas em Python: Quais as Semelhanças?

Iniciaremos examinando os pontos em comum entre listas e tuplas. Para uma melhor compreensão, forneceremos exemplos práticos de ambas as estruturas.

#1. Iteráveis em Python

Em Python, listas são delimitadas por colchetes, enquanto tuplas são definidas por parênteses. É importante destacar que uma tupla também pode ser criada como uma sequência de valores separados por vírgula, sem a necessidade dos parênteses.

Ambas as estruturas são iteráveis, o que permite percorrê-las com um loop “for”.

O código abaixo demonstra a iteração em uma lista:

nums = [2,6,7,10]
print(f"O tipo de nums é {type(nums)}")
for num in nums:
  print(num)

# Saída
O tipo de nums é <class 'list'>
2
6
7
10

Como demonstrado abaixo, você também pode percorrer uma tupla utilizando um loop:

nums = (2,6,7,10)

# Observação: nums = 2,6,7,10 também é uma tupla válida. Se necessário, verifique!

print(f"O tipo de nums é {type(nums)}")
for num in nums:
  print(num)

# Saída
O tipo de nums é <class 'tuple'>
2
6
7
10

#2. Suporte à Criação a Partir de Sequências

Outra semelhança entre listas e tuplas é a capacidade de serem criadas a partir de sequências existentes, como strings.

sample_str = "Programando!"

O código a seguir mostra como `list(string)` retorna uma lista, onde cada item é um caractere da string:

list_from_str = list(sample_str)
print(list_from_str)

# Saída
['P', 'r', 'o', 'g', 'r', 'a', 'm', 'a', 'n', 'd', 'o', '!']

De maneira similar, uma tupla pode ser formada a partir de uma string ou outra sequência usando `tuple(sequence)`. O código abaixo ilustra como realizar essa operação:

tuple_from_str = tuple(sample_str)
print(tuple_from_str)

# Saída
('P', 'r', 'o', 'g', 'r', 'a', 'm', 'a', 'n', 'd', 'o', '!')

#3. Suporte a Indexação e Fatiamento

Python implementa indexação baseada em zero, onde o primeiro elemento está no índice zero, o segundo no índice um, e assim sucessivamente. Além disso, Python permite indexação negativa, onde o último elemento está no índice -1, o penúltimo no índice -2, e assim por diante.

list_from_str = ['P', 'r', 'o', 'g', 'r', 'a', 'm', 'a', 'n', 'd', 'o', '!']
print(list_from_str[1])
# r

O item no índice -2 é o penúltimo, ‘o’.

tuple_from_str = ('P', 'r', 'o', 'g', 'r', 'a', 'm', 'a', 'n', 'd', 'o', '!')
print(tuple_from_str[-2])
# o

O fatiamento é útil quando você quer trabalhar com uma parte específica de uma lista ou tupla. A sintaxe `lista[inicio:fim]` retorna uma fatia da lista, começando no índice `inicio` e indo até o índice `fim` – 1. O valor padrão para `inicio` é 0 e para `fim` é o último elemento do iterável.

É possível fatiar tuplas utilizando a mesma sintaxe. Vamos criar fatias a partir da lista e tupla que criamos anteriormente:

list_from_str = ['P', 'r', 'o', 'g', 'r', 'a', 'm', 'a', 'n', 'd', 'o', '!']
print(list_from_str[0:5])

# Saída
['P', 'r', 'o', 'g', 'r']

Além dos valores inicial e final, você pode especificar um valor de passo. A sintaxe `tuple[inicio:fim:passo]` retorna uma fatia da tupla, do índice `inicio` até `fim` – 1, com incrementos de `passo`.

tuple_from_str = ('P', 'r', 'o', 'g', 'r', 'a', 'm', 'a', 'n', 'd', 'o', '!')
print(tuple_from_str[::2])

# Saída
('P', 'o', 'r', 'm', 'n', 'o')

Neste caso, definimos o valor do passo como 2, então a fatia contém cada segundo elemento.

#4. Coleções de Diversos Tipos de Dados

Nos exemplos anteriores, todos os itens de cada lista ou tupla eram do mesmo tipo de dados.

No entanto, é perfeitamente possível armazenar valores de tipos de dados distintos em uma única lista ou tupla.

No exemplo abaixo, a lista `aluno_lista` contém o nome de um aluno como uma string, a idade como um número inteiro e a nota como um número de ponto flutuante:

student_list = ["Ricardo",25,92.5]
for item in student_list:
  print(f"{item} é do tipo {type(item)}")

# Saída
Ricardo é do tipo <class 'str'>
25 é do tipo <class 'int'>
92.5 é do tipo <class 'float'>

Podemos criar um exemplo similar utilizando uma tupla:

student_tuple = ("Ana",23,99.5)
for item in student_tuple:
  print(f"{item} é do tipo {type(item)}")

# Saída
Ana é do tipo <class 'str'>
23 é do tipo <class 'int'>
99.5 é do tipo <class 'float'>

#5. Suporte ao Teste de Associação

Tanto listas quanto tuplas permitem a verificação de existência de um item específico. Se você precisa verificar se um item está presente em uma lista ou tupla, utilize o operador `in`.

A expressão `item in iteravel` retorna `True` se o `iterável` contiver o `item`; caso contrário, retorna `False`.

"Carlos" in student_list
# False

"Ana" in student_tuple
# True

Até o momento, exploramos as semelhanças entre listas e tuplas em Python. A seguir, examinaremos as principais diferenças entre as duas estruturas de dados.

Tuplas vs Listas em Python: Quais as Diferenças?

#1. Mutabilidade de Listas vs Imutabilidade de Tuplas

A diferença mais crucial entre listas e tuplas é que tuplas são imutáveis, ou seja, não podem ser modificadas após a criação.

▶️ Veja um exemplo:

tuple1 = ("Java","Python","C++")
tuple1[0] = "Rust"

# Saída
----> 2 tuple1[0] = "Rust"

TypeError: 'tuple' object does not support item assignment

Já listas são estruturas de dados mutáveis, permitindo a alteração de um item em um índice específico, como demonstrado no código a seguir:

list1 = ["Java","Python","C++"]
list1[0] = "Rust"
print(list1)

# Saída
['Rust', 'Python', 'C++']

#2. Listas de Comprimento Variável vs Tuplas de Comprimento Fixo

Listas em Python são estruturas de dados de comprimento variável.

Você pode realizar as seguintes operações:

  • Adicionar um item ao final da lista
  • Adicionar itens de outra lista ao final da lista atual
  • Remover itens em um índice específico da lista
list1 = [2,3,4,5]

# adicionar um item ao final
list1.append(9)
print(list1)

# adicionar itens da list2 ao final da list1
list2 = [0,7]
list1.extend(list2)
print(list1)

# remover um item da list1
list1.pop(0)
print(list1)

▶️ A saída do código acima:

# Saída
[2, 3, 4, 5, 9]
[2, 3, 4, 5, 9, 0, 7]
[3, 4, 5, 9, 0, 7]

Tuplas são estruturas de dados de comprimento fixo. Portanto, você não pode adicionar ou remover elementos de uma tupla existente. No entanto, é possível redefinir a tupla para conter elementos diferentes.

tuple1 = (2,4,6,8)
tuple1 = (1,8,9)
print(tuple1)

# Saída
(1, 8, 9)

#3. Tamanho na Memória

Baseado no que aprendemos anteriormente, listas são estruturas de dados de comprimento variável.

Ao definir uma lista, um tamanho específico de memória é alocado inicialmente. Ao modificar a lista usando os métodos `append()` ou `extend()`, memória adicional é alocada para armazenar os novos elementos, geralmente em um bloco maior do que o necessário para os novos itens.

Por isso, é necessário controlar tanto o número de itens na lista quanto o espaço alocado. Além disso, como listas são de tamanho variável, existe um ponteiro que aponta para o endereço dos itens na lista. Em consequência, uma lista de tamanho `k` ocupa mais memória do que uma tupla com os mesmos `k` elementos.

Veja uma representação simples:

Você pode usar o método `getsizeof()` do módulo `sys` para obter o tamanho de um objeto na memória.

import sys

list1 = [4,5,9,14]
list_size = sys.getsizeof(list1)
print(f"Tamanho da lista:{list_size}")

tuple1 = (4,5,9,14)
tuple_size = sys.getsizeof(tuple1)
print(f"Tamanho da tupla:{tuple_size}")

Como confirmado pela saída abaixo, listas ocupam mais memória que tuplas para o mesmo número e valor de elementos:

# Saída
Tamanho da lista:104
Tamanho da tupla:88

Quando Utilizar uma Tupla em Python?

Com base nas diferenças e semelhanças entre listas e tuplas, você já sabe que, se precisar de uma coleção mutável, deve usar uma lista.

Mas em que situações você deve optar por usar uma tupla?

Essa será nossa exploração na próxima seção.

#1. Coleção Somente Leitura

Sempre que você precisar de uma coleção imutável, declare-a como uma tupla. Por exemplo, `color = (243,55,103)`, uma tupla contendo os valores RGB correspondentes a um tom de cor. Ao definir a cor como uma tupla, você garante que ela não poderá ser modificada.

Em resumo, sempre que precisar que uma coleção seja somente leitura – cujos valores não podem ser modificados durante a execução do programa – considere utilizar uma tupla, evitando modificações não intencionais nos valores.

#2. Chaves de Dicionário

Por exemplo, você pode criar um dicionário utilizando itens de uma lista, como `lista_de_chaves`, como chaves. O método `dict.fromkeys()` permite criar um dicionário a partir de uma lista.

key_list = list("ABCD")
dict.fromkeys(key_list)

# Saída
{'A': None, 'B': None, 'C': None, 'D': None}

Se você modificar a lista antes de criar o dicionário, por exemplo, alterando o primeiro item (índice 0) para ‘D’, o que acontecerá com a chave ‘A’?

Ao tentar criar um dicionário a partir de `lista_de_chaves` e tentar acessar o valor correspondente à chave ‘A’, você receberá um erro `KeyError`. Isso ocorre porque as chaves do dicionário devem ser únicas, e não é possível ter um segundo ‘D’ como chave.

key_list[0] = 'D'

dict.fromkeys(key_list)['A']

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-31-c90392acc2cf> in <module>()
----> 1 dict.fromkeys(key_list)['A']

KeyError: 'A'
dict.fromkeys(key_list)
{'B': None, 'C': None, 'D': None} # A não é mais uma chave.

Se, em vez disso, você utilizar uma tupla, essa modificação seria impossível, diminuindo a probabilidade de erros. Portanto, você deve preferir criar um dicionário usando os itens de uma tupla como chaves.

key_tuple = tuple("ABCD")
dict.fromkeys(key_tuple)
{'A': None, 'B': None, 'C': None, 'D': None}

key_tuple[0] = 'D'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-2cecbefa7db2> in <module>()
----> 1 key_tuple[0] = 'D'

TypeError: 'tuple' object does not support item assignment

#3. Argumentos de Funções

A imutabilidade das tuplas também as torna adequadas para serem passadas como argumentos de funções.

Considere a função `calcula_volume()`, que calcula o volume de um paralelepípedo dadas as dimensões: comprimento, largura e altura.

def calcula_volume(dimensoes):
  c,l,a = dimensoes
  return c*l*a

Suponha que essas dimensões estejam disponíveis em uma lista chamada `dimensoes`. Ao chamar `calcula_volume()` com `dimensoes` como argumento, o volume será calculado.

dimensoes = [2,8,5]
calcula_volume(dimensoes)
# Saída
80

Você sempre pode alterar as dimensões armazenadas em uma lista.

dimensoes = [20,8,5]
calcula_volume(dimensoes)
# Saída
800

No entanto, algumas vezes você precisará que os valores permaneçam constantes e não sofram modificações. É nesses casos que você deve considerar armazenar os argumentos em uma tupla, passando-a para a função.

#4. Valores de Retorno de Funções

Em Python, você frequentemente encontrará tuplas como valores de retorno de funções. Quando uma função retorna múltiplos valores, Python os retorna implicitamente em uma tupla.

Considere a seguinte função `retorna_pares()`:

def retorna_pares(num):
  pares = [i for i in range(num) if (i%2==0)]
  return pares,len(pares)
  • Recebe um número `num` como argumento.
  • Retorna a lista de números pares no intervalo `[0,num)` e o tamanho dessa lista.

Vamos definir o valor de `num` para 20 e chamar a função:

num = 20

Ao chamar `retorna_pares()`, a função retorna dois valores em uma tupla. Você pode verificar o tipo utilizando a função `type()`:

type(retorna_pares(num)) # <class 'tuple'>

Você pode exibir o valor de retorno para confirmar que é uma tupla, contendo a lista de números pares como o primeiro item e o tamanho da lista como o segundo item:

print(retorna_pares(num))
# Saída
([0, 2, 4, 6, 8, 10, 12, 14, 16, 18], 10)

Como há dois itens na tupla, é possível descompactá-los em duas variáveis, como demonstrado abaixo:

pares, quantidade = retorna_pares(num)

print(pares)
print(quantidade)

# Saída
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
10

Conclusão

Espero que este guia tenha fornecido uma comparação detalhada entre tuplas e listas em Python.

Vamos recapitular com um breve resumo:

  • Listas e tuplas são estruturas de dados nativas em Python.
  • Semelhanças: iteráveis, suporte a indexação, fatiamento, armazenamento de diferentes tipos de dados e uso do operador para teste de associação.
  • Diferença chave: listas são mutáveis e tuplas são imutáveis.
  • Outras diferenças: tuplas têm comprimento fixo e listas têm comprimento variável, e tuplas ocupam menos espaço na memória.
  • Quando usar uma tupla? Em coleções imutáveis, chaves de dicionário e argumentos de funções.

Para praticar e consolidar seu aprendizado, confira alguns projetos em Python ou explore métodos para remover itens duplicados de listas em Python. Continue aprendendo e codificando! 👩🏽‍💻