Pular para o conteúdo
Ramos da Informática - Comunidade de Desenvolvedores

Torne-se um desenvolvedor FullStack: Pacote completo de formação desenvolvedor Frontend e Backend utilizando as linguagens de programação e frameworks mais procurados no mercado de trabalho. Mais informações, aqui. Faça o download do E-BookGuia Completo Para Se Tornar um(a) Desenvolvedor(a) Full-Stack, Começando do ZERO”.

Engenheiro de Software, autor de livros sobe tecnologia e negócios. É mantenedor do site Ramos da Informática. Hobbies: investir em ações, natação e finanças.

Engenheiro de Software, autor de livros sobe tecnologia e negócios. É mantenedor do site Ramos da Informática. Hobbies: investir em ações, natação e finanças.

admin

Todos os artigos deste autor

“Python ‘!=’ não é ‘is not’: Comparando objetos em Python”

Chatbots com Whatsapp e Cielo integrados Nesse curso, eu vou te mostrar como o consumidor poder realizar um pagamento por dentro do aplicativo do WhatsApp, aonde o seu cliente vai entrar numa conversa como entraria numa conversa com qualquer pessoa ou com a sua empresa, navegar entre os produtos/serviços em menus simples enviados pelo chatbot, adicionar esses produtos/serviços no carrinho de compras, e num determinado ponto do chat, um link exclusivo é enviado para o cliente preencher os dados do cartão de crédito. No final, a análise é devolvida para o Whatsapp no qual a conversa foi iniciada. Inscreva-se.

Há uma diferença sutil entre o operador de identidade Python (is) e o operador de igualdade (==). Seu código pode funcionar bem quando você usa o operador Python “is” para comparar números, até que, de repente não funciona mais. Você deve ter ouvido em algum lugar que o operador Python “is” é mais rápido que o operador “==” ou pode parecer que ele é mais Pythônico. No entanto, é crucial ter em mente que esses operadores não se comportam da mesma maneira.

O operador (==) compara o valor ou a igualdade de dois objetos, enquanto o operador Python “is” verifica se duas variáveis apontam para o mesmo objeto na memória. Na grande maioria dos casos, isso significa que você deve usar os operadores de igualdade “==” e “!=”, Exceto quando estiver comparando com None

Neste tutorial, você aprenderá:

  1. Qual a diferença entre igualdade de objetos e identidade.
  2. Quando usar operadores de igualdade e identidade para comparar objetos
  3. O que estes operadores Python fazem “Por baixo dos panos”.
  4. Por que usar “is” e não comparar valores leva a um comportamento inesperado.
  5. Como escrever um método de classe __eq__() personalizado para definir o comportamento do operador de igualdade

 

Comparar identidade com os operadores “is” e “is not”

Os operadores Python “is” e “is not” são operadores que comparam a identidade de dois objetos. No CPython, esse é o endereço de memória deles. Tudo no Python é um objeto, e cada objeto é armazenado em um local específico da memória. Os operadores “is” e “is not” são operadores que verificam se duas variáveis se referem ao mesmo objeto na memória.

Nota: Lembre-se de que objetos com o mesmo valor geralmente são armazenados em endereços de memória separados.

Você pode usar id() para verificar a identidade de um objeto. Execute help(id) para ver uma ajuda dessa função.

>> help(id)
Ajuda na identificação da função integrada nos módulos internos:

id(obj,/)
Retorna a identidade de um objeto.

Isso é garantido como único entre objetos existentes simultaneamente.
(O CPython usa o endereço de memória do objeto.)

Agora execute o método id conforme abaixo e veja o resultado:

>> id(id)
2570892442576

Será exibido o endereço de memória em que o próprio ID da função interna do Python está armazenado.

Existem alguns casos comuns em que objetos com o mesmo valor terão o mesmo ID por padrão. Por exemplo, os números -5 a 256 são internados no CPython. Cada número é armazenado em um local fixo e singular na memória, o que economiza memória para números inteiros comumente usados.

Você pode usar “sys.intern()” para estender sequências de caracteres para desempenho. Esta função permite comparar os endereços de memória em vez de comparar as cadeias caractere por caractere:

>> from sys import intern
>> a = ‘olá mundo’
>> b = ‘olá mundo’
>> a is b
False
>> id(a)
1603648396784
>> id(b)
1603648426160

>> a = intern(a)
>> b = intern(b)
>> a is b
True
>> id(a)
1603648396784
>> id(b)
1603648396784

As variáveis a e b inicialmente apontam para dois objetos diferentes na memória, conforme mostrado por seus diferentes IDs. Ao interná-los, você garante que a e b apontam para o mesmo objeto na memória. Qualquer nova sequência com o valor ‘olá mundo’ agora será criada em um novo local de memória, mas quando você internar essa nova sequência, verifique se ela aponta para o mesmo endereço de memória que o primeiro ‘olá mundo’ que você inseriu.

Nota: Embora o endereço de memória de um objeto seja único a qualquer momento, ele varia entre execuções do mesmo código e depende da versão do CPython e da máquina na qual ele é executado.

Outros objetos internados por padrão são None, True, False e sequências de caracteres simples. Lembre-se de que na maioria das vezes, objetos diferentes com o mesmo valor serão armazenados em endereços de memória separados. Isso significa que você não deve usar o operador Python “is” para comparar valores.

Quando apenas alguns números inteiros são internados

Nos bastidores, o Python armazena objetos com valores comumente usados (por exemplo, os inteiros -5 a 256) para economizar memória. O seguinte código mostra como apenas alguns números inteiros têm um endereço de memória fixo.

>> a = 256
>> b = 256
>> a is b
True
>> id(a)
1638894624
>> id(b)
1638894624

>> a = 257
>> b = 257
>> a is b
False

>> id(a)
2570926051952
>> id(b)
2570926051984

Inicialmente, a e b apontam para o mesmo objeto interno na memória, mas quando seus valores estão fora do intervalo de números inteiros comuns (variando de -5 a 256), eles são armazenados em endereços de memória separados.

Quando várias variáveis apontam para o mesmo objeto

Ao usar o operador de atribuição (=) para tornar uma variável igual à outra, essas variáveis apontam para o mesmo objeto na memória. Isso pode levar a um comportamento inesperado para objetos mutáveis

>> a = [1, 2, 3]
>> b = a
>> a
[1, 2, 3]
>> b
[1, 2, 3]

>> a.append(4)
>> a
[1, 2, 3, 4]
>> b
[1, 2, 3, 4]

>> id(a)
2570926056520
>> id(b)
2570926056520

O que acabou de acontecer? Você adiciona um novo elemento a, mas agora b também contém esse elemento! Bem, na linha em que b = a, você define b para apontar para o mesmo endereço de memória que a, para que ambas as variáveis agora se refiram ao mesmo objeto.

Se você definir essas listas independentemente uma da outra, elas serão armazenadas em diferentes endereços de memória e se comportarão de forma independente

>> a = [1, 2, 3]
>> b = [1, 2, 3]
>> a is b
False
>> id(a)
2356388925576
>> id(b)
2356388952648

Como a e b agora se referem a diferentes objetos na memória, alterar um não afeta o outro.

Comparando a igualdade com os operadores == e != Python

Lembre-se de que objetos com o mesmo valor geralmente são armazenados em endereços de memória separados. Use os operadores de igualdade == e != se desejar verificar se dois objetos têm ou não o mesmo valor, independentemente de onde estão armazenados na memória. Na grande maioria dos casos, é isso que você deseja fazer.

Quando a cópia do objeto é igual, mas não idêntica

No exemplo abaixo, você define b como uma cópia de a (que é um objeto mutável, como uma lista ou um dicionário). Ambas as variáveis terão o mesmo valor, mas cada uma será armazenada em um endereço de memória diferente.

>> a = [1, 2, 3]
>> b = a.copy()
>> a
[1, 2, 3]
>> b
[1, 2, 3]

>> a == b
True
>> a is b
False

>> id(a)
2570926058312
>> id(b)
2570926057736

a e b estão agora armazenados em endereços de memória diferentes, portanto, a e b não retornará mais True. No entanto, a == b retorna True porque os dois objetos têm o mesmo valor.

Como funciona a comparação por igualdade

A mágica do operador de igualdade (==) acontece no método da classe __eq__() do objeto à esquerda do sinal (==).

Nota: Esse é o caso, a menos que o objeto à direita seja uma subclasse do objeto à esquerda. Para mais informações, consulte a documentação oficial.

Esse é um método de classe magic chamado sempre que uma instância dessa classe é comparada com outro objeto. Se esse método não for implementado, == compara os endereços de memória dos dois objetos por padrão.

Como exercício, crie uma classe SillyString que herda de str e implemente __eq__() para comparar se o comprimento dessa string é igual ao comprimento do outro objeto.

class SillyString(str):

Este método é chamado ao usar (==) no objeto

def eq(self, other):
print(f’comparando {self} no {other}’)

Retorna True se self e other tiverem o mesmo comprimento

return len(self) == len(other)

Agora, um ‘olá mundo’ do SillyString deve ser igual à sequência ‘olá mundo’ e até qualquer outro objeto com o mesmo comprimento.

>> #Compare duas strings
>> ‘olá mundo’ == ‘mundo olá’
False

>> # Compare a string com a SillyString
>> ‘olá mundo’ == SillyString(‘olá mundo’)
comparando olá mundo com olá mundo
True

>> # Compare a SillyString com uma lista
>> SillyString(‘olá mundo’) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
comparando olá mundo com [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
True

É claro que esse é um comportamento tolo para um objeto que se comporta como uma string, mas ilustra o que acontece quando você compara dois objetos usando ==. O operador != fornece a resposta inversa disso, a menos que um método específico da classe __ne__() seja implementado.

O exemplo acima também mostra claramente por que é uma boa prática usar o operador Python “is” para comparar com None, em vez do operador ==. Além de ser mais rápido, ele compara os endereços de memória, mas também é mais seguro, pois não depende da lógica de nenhum método de classe __eq__().

Comparando os operadores de comparação Python

Como regra geral, você sempre deve usar os operadores de igualdade == e !=, Exceto quando estiver comparando a None.

Use os operadores Python == e != para comparar a igualdade de objetos. Aqui, você geralmente está comparando o valor de dois objetos. É disso que você precisa para comparar se dois objetos têm ou não o mesmo conteúdo e não se importa com o local em que estão armazenados na memória.

Use os operadores Python “is” e “is not” quando você deseja comparar a identidade do objeto. Aqui, você está comparando se duas variáveis apontam ou não para o mesmo objeto na memória. O principal caso de uso desses operadores é quando você está comparando com None. É mais rápido e seguro comparar com None pelo endereço de memória do que usando métodos de classe.

Variáveis com o mesmo valor geralmente são armazenadas em endereços de memória separados. Isso significa que você deve usar == e != para comparar seus valores e usar o “is” e “is not” apenas quando você deseja verificar se duas variáveis apontam para o mesmo endereço de memória.

Conclusão

Neste tutorial, você aprendeu que == e != comparam o valor de dois objetos, enquanto o “is” e “is not” comparam se duas variáveis se referem ao mesmo objeto na memória. Se você mantiver essa distinção em mente, poderá evitar um comportamento inesperado no seu código.

Se você quiser ler mais sobre o maravilhoso mundo da internação de objetos e o operador Python “is”, consulte “Porque você quase nunca deve usar ‘is’ no Python“. Você também pode ver como pode usar o sys.intern() para otimizar o uso da memória e os tempos de comparação de strings, embora as chances sejam de que o Python já lide automaticamente com isso nos bastidores.

Agora que você aprendeu o que os operadores de igualdade e identidade fazem “por baixo dos panos”, pode tentar escrever seus próprios métodos de classe __eq__(), que definem como as instâncias dessa classe são comparadas ao usar o operador ==. Vá e aplique seu novo conhecimento sobre esses operadores de comparação Python!

Fonte:

https://realpython.com/python-is-identity-vs-equality

Este artigo foi importado automaticamente por fazer parte do Planetário Dev. Quer fazer parte deste HUB de conteúdos? Faça parte do Planetário e veja as vantagens.

Não tem site ou blog? Seja um autor do site e ainda pode ser remunerado.

Mais sobre Newsletters?

32 melhores newsletters sobre negócios, startups e tecnologia para assinar em 2022

 

Facebook
LinkedIn
Twitter
Pinterest
Reddit
Telegram
WhatsApp
Email
Print

Relacionados

Deixe uma resposta