Um operador de comparação em Python (também chamado de operador relacional de Python) analisa os valores de dois operandos e devolve um valor Boolean, True ou False, consoante a condição comparison seja ou não satisfeita.
A tabela abaixo mostra os operadores de comparação mais comuns do Python:
| Operador | Operação | Descrição |
|---|---|---|
> |
"maior que" |
a > b é True se a for estritamente maior, em valor, que b
|
< |
"menor que" |
a < b é True se a for estritamente menor, em valor, que b
|
== |
"igual a" |
a == b é True se a for estritamente igual a b em valor |
>= |
"maior ou igual a" |
a >= b é True se a > b OU a == b em valor |
<= |
"menor ou igual a" |
a <= b é True se a < b ou a == b em valor |
!= |
"diferente de" |
a != b é True se a == b for False
|
is |
"identidade" |
a is b é True se e somente se a e b forem o mesmo objeto
|
is not |
"identidade negada" |
a is not b é True se e somente se a e b não forem o mesmo objeto
|
in |
"teste de pertença" |
a in b é True se a for membro, subconjunto ou elemento de b
|
not in |
"teste de pertença negado" |
a not in b é True se a não for membro, subconjunto ou elemento de b
|
Todos têm a mesma prioridade (que é superior à das operações Boolean, mas inferior à das operações aritméticas ou bit a bit).
Objetos de tipos diferentes (exceto os tipos numéricos) nunca são considerados iguais por predefinição.
Instâncias não idênticas de uma class também não são consideradas iguais, a menos que a class defina métodos especiais de comparação rica que personalizem o comportamento de comparação predefinido do object.
Para mais (muitos) detalhes, consulta Comparações de valores na documentação do Python.
Os tipos numéricos são (em grande parte) uma exceção a esta regra de correspondência de tipos.
Um integer pode ser considerado igual a um float (ou um octal igual a um hexadecimal), desde que os tipos possam ser convertidos implicitamente para comparação.
Para os outros tipos numéricos (complexos, decimais, frações), os operadores de comparação estão definidos onde "fazem sentido" (onde a conversão implícita não altera o resultado), mas lançam um TypeError se os objetos subjacentes não puderem ser convertidos com precisão para comparação.
Para mais informações sobre as regras que o Python usa para a conversão numérica, consulta conversões aritméticas na documentação do Python.
>>> import fractions
# A string cannot be converted to an int.
>>> 17 == '17'
False
# An int can be converted to float for comparison.
>>> 17 == 17.0
True
# The fraction 6/3 can be converted to the int 2
# The int 2 can be converted to 0b10 in binary.
>>> 6/3 == 0b10
True
# An int can be converted to a complex
# number with a 0 imaginary part.
>>> 17 == complex(17)
True
# The fraction 2/5 can be converted to the float 0.4
>>> 0.4 == 2/5
True
>>> complex(2/5, 1/2) == complex(0.4, 0.5)
True
Qualquer comparação ordenada de um número com um tipo NaN (não é um número) é False.
Um efeito secundário confuso da definição de NaN do Python é que NaN nunca é igual a NaN.
Se tiveres curiosidade em saber porque NaN foi definido desta forma no Python, este artigo do Stack Overflow sobre NaN, sobre a definição da norma internacional, é uma leitura interessante.
>>> x = float('NaN')
>>> 3 < x
False
>>> x < 3
False
# NaN never compares equal to NaN
>>> x == x
False
As strings (str) são comparadas lexicograficamente, usando os seus pontos de código Unicode individuais (o resultado de passar cada ponto de código da str à função incorporada ord(), que devolve um int).
Se todos os pontos de código de ambas as strings coincidirem e estiverem na mesma ordem, as duas strings são consideradas iguais.
Esta comparação é feita par a par: primeiro com primeiro, segundo com segundo, etc.
No Python 3.x, str e bytes não podem ser diretamente coagidos nem comparados.
>>> 'Python' > 'Rust'
False
>>> 'Python' > 'JavaScript'
True
# Examples with Mandarin.
# hello < goodbye
>>> '你好' < '再见'
True
# ord() of first characters
>>> ord('你'), ord('再')
(20320, 20877)
# ord() of second characters
>>> ord('好'), ord('见')
(22909, 35265)
# And with Korean words.
# Pretty < beautiful.
>>> '예쁜' < '아름다운'
False
>>> ord('예'), ord('아')
(50696, 50500)
Os tipos de dados contentores (lists, tuples, sets, dicts, etc.) também são comparados lexicograficamente: são iguais se ambos os contentores tiverem os mesmos dados e os mesmos tipos de dados (no caso das lists e das tuples, também têm de ter a mesma ordem); caso contrário, são diferentes.
>>> [1, 2] == [1, 2]
True
# But if the data is not in the same order, they are not equal.
>>> [2, 1] == [1, 2]
False
# The same holds true for tuples
>>> (3,4,5) == (5,4,3)
False
# Length is also compared
>>> [1, 2] < [1, 2, 3]
True
# Comparing dicts
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 18}
False
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 19}
True
Os operadores de comparação podem ser encadeados arbitrariamente.
Repara que a avaliação de uma expressão ocorre da left para a right.
Por exemplo, x < y <= z é equivalente a x < y and y <= z, exceto que y é avaliado apenas uma vez.
Em ambos os casos, z não é avaliado de forma alguma quando se verifica que x < y é False.
A isto chama-se frequentemente short-circuit evaluation: a avaliação para se o valor de verdade da expressão já tiver sido determinado.
O Short circuiting é suportado por vários operadores Boolean e funções, e também pelo encadeamento de comparações no Python.
Ao contrário de muitas outras linguagens de programação, incluindo C, C++, C# e Java, as expressões encadeadas como a < b < c no Python têm uma interpretação matemática e uma precedência convencionais.
>>> x = 2
>>> y = 5
>>> z = 10
>>> x < y < z
True
>>> x < y > z
False
>>> x > y < z
False
Os operadores is e is not testam a identidade do objeto, em oposição ao valor do objeto.
A identidade de um objeto nunca muda após a criação e pode ser obtida com a função id().
<apple> is <orange> é avaliado como True se e somente se id(<apple>) == id(<orange>).
<apple> is not <orange> devolve o inverso.
Devido ao seu estatuto de singleton, None e NotImplemented devem ser sempre comparados com outros elementos usando is e is not.
Consulta a documentação de referência do Python sobre comparações de valores e a PEP8 para mais detalhes sobre esta convenção.
# A list of favorite numbers.
>>> my_fav_numbers = [1, 2, 3]
>>> your_fav_numbers = my_fav_numbers
>>> my_fav_numbers is your_fav_numbers
True
# The returned id will differ by system and Python version.
>>> id(my_fav_numbers)
4517478208
# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
# Assigning a new name does not create a new object.
>>> id(your_fav_numbers)
4517478208
>>> my_fav_numbers is not your_fav_numbers
False
>>> my_fav_numbers is not None
True
>>> my_fav_numbers is NotImplemented
False
Os operadores in e not in testam a pertença.
<fish> in <soup> é avaliado como True se <fish> for membro de <soup> (se <fish> for um subconjunto de <soup> ou estiver contido em <soup>) e é avaliado como False caso contrário.
<fish> not in <soup> devolve a negação, ou o oposto de <fish> in <soup>.
Para os tipos string e bytes, <name> in <fullname> é True se e somente se <name> for uma substring de <fullname>.
# A set of lucky numbers.
>>> lucky_numbers = {11, 22, 33}
>>> 22 in lucky_numbers
True
>>> 44 in lucky_numbers
False
# A dictionary of employee information.
>>> employee = {'name': 'John Doe', 'id': 67826, 'age': 33, 'title': 'ceo'}
# Checking for the membership of certain keys.
>>> 'age' in employee
True
>>> 33 in employee
False
>>> 'lastname' not in employee
True
# Checking for substring membership
>>> name = 'Super Batman'
>>> 'Bat' in name
True
>>> 'Batwoman' in name
False
O comportamento de comparação dos objetos pode ser personalizado através da implementação de rich comparison methods.
Para mais informações, consulta Tutorial de Python: classes, Classes e métodos mágicos em Python (Dan Bader) e Nomes de métodos especiais.