HOWTO · Python
Como comparar tuplas em Python
Aprenda a comparar tuplas em Python de forma eficaz com este guia abrangente. Explore vários métodos, incluindo verificações de igualdade, verificações de desigualdade e comparações lexicográficas. Descubra como utilizar funções integradas para a comparação elemento a elemento. Quer seja um principiante ou um programador experiente, melhore as suas competências de programação com exemplos práticos e explicações claras.
Nesta página
Ao trabalhar com Python, pode precisar frequentemente de comparar tuplas. As tuplas são sequências imutáveis, o que significa que, uma vez criadas, não podem ser modificadas. Esta característica torna-as particularmente úteis para armazenar coleções fixas de itens. Comparar tuplas pode ajudá-lo a determinar a sua igualdade, ordem e até o seu conteúdo.
Neste artigo, vamos explorar como o Python compara tuplas, desde simples verificações de igualdade até à ordenação lexicográfica, e como as comparações se comportam quando as tuplas diferem em tipo, comprimento ou aninhamento.
Como o Python compara tuplas
O Python compara tuplas lexicograficamente, da mesma forma que as palavras são ordenadas num dicionário. Compara os primeiros elementos de cada tupla; se eles diferirem, essa primeira diferença decide a comparação, e os elementos restantes nunca são examinados. Se os primeiros elementos forem iguais, passa para o par seguinte, e assim por diante, até encontrar uma diferença ou ficar sem elementos. Se uma tupla for um prefixo da outra — todos os seus elementos correspondem ao início da tupla mais longa — a tupla mais curta é considerada menor do que a mais longa.
O operador de igualdade (==) verifica se ambas as tuplas têm os mesmos elementos na mesma ordem, e o operador de desigualdade (!=) é o seu oposto exato:
tuple1 = (1, 2, 3)
tuple2 = (1, 2, 3)
tuple3 = (1, 2, 4)
print(tuple1 == tuple2)
print(tuple1 == tuple3)
print(tuple1 != tuple3)
Saída:
True
False
True
Os operadores de ordem (<, <=, >, >=) aplicam a mesma varredura elemento a elemento, utilizando a ordem própria de cada par para decidir:
tuple1 = (1, 2, 3)
tuple2 = (1, 2, 4)
tuple3 = (1, 2)
print(tuple1 < tuple2)
print(tuple1 > tuple3)
Saída:
True
True
Aqui, tuple1 é menor que tuple2 porque os dois primeiros elementos são iguais e 3 < 4. E tuple1 é maior que tuple3 porque tuple3 é um prefixo de tuple1, pelo que a tupla mais longa se ordena depois da mais curta.
Lidar com diferentes tipos, comprimentos e tuplas aninhadas
A igualdade e a ordem não tratam os tipos mistos da mesma maneira, e confundi-los é uma fonte comum de expectativas erradas.
A igualdade nunca levanta um erro por causa dos tipos. Dois elementos de tipos diferentes são simplesmente desiguais — com a exceção numérica habitual de que valores como 1 e 1.0 são considerados iguais —, pelo que uma comparação de tuplas com == retorna False, e != retorna True, sem que ninguém verifique os tipos primeiro:
tuple1 = (1, "a", 3)
tuple2 = (1, 2, 3)
print(tuple1 == tuple2)
print(tuple1 != tuple2)
Saída:
False
True
A ordem é mais rigorosa. No momento em que uma comparação de ordem atinge um par de elementos que não podem ser ordenados um em relação ao outro, como uma string contra um inteiro, ela levanta um TypeError em vez de retornar um resultado:
tuple1 = (1, "a", 3)
tuple2 = (1, 2, 3)
print(tuple1 < tuple2)
Saída:
TypeError: '<' not supported between instances of 'str' and 'int'
Os primeiros elementos são iguais, pelo que a comparação passa para "a" contra 2 — e as strings e os inteiros não têm qualquer ordem entre si, daí o erro. Note que isto só acontece se a comparação atingir realmente o par incompatível: (0, "a") < (1, 2) retorna False sem erro, porque os primeiros elementos já o decidem.
Comprimentos diferentes interagem com uma popular verificação de igualdade elemento a elemento de uma forma que é fácil não perceber. Combinar all() com zip() compara os pares que zip() produz, e zip() para na tupla mais curta — pelo que os elementos finais sem correspondência são silenciosamente ignorados:
tuple1 = (1, 2, 3)
tuple2 = (1, 2)
print(all(a == b for a, b in zip(tuple1, tuple2)))
print(len(tuple1) == len(tuple2) and all(a == b for a, b in zip(tuple1, tuple2)))
Saída:
True
False
A primeira linha relata True apesar de as tuplas não serem iguais, porque o 3 final nunca é comparado. Se utilizar este padrão — é útil para tuplas grandes ou para lógica personalizada por elemento — combine-o sempre com uma verificação de comprimento, como na segunda linha.
As tuplas aninhadas não precisam de qualquer tratamento especial: um elemento tupla é comparado com as mesmas regras de qualquer outro elemento, de forma recursiva. (1, 2) dentro de uma tupla ordena-se antes de (3, 5) dentro de outra, porque os seus próprios primeiros elementos diferentes o decidem:
tuple1 = ((1, 2), (3, 4))
tuple2 = ((1, 2), (3, 5))
print(tuple1 < tuple2)
print(tuple1 == tuple2)
Saída:
True
False
Em resumo: recorra a == e != quando só precisa de saber se duas tuplas são iguais — funcionam com qualquer conteúdo. Utilize os operadores de ordem quando precisa da ordem relativa, e certifique-se de que os elementos a que a comparação irá realmente chegar podem ser ordenados uns em relação aos outros.