Em um comentário sobre essa pergunta , vi uma declaração que recomendava o uso de
result is not None
vs
result != None
Eu queria saber qual é a diferença, e por que um pode ser recomendado em detrimento do outro?
Em um comentário sobre essa pergunta , vi uma declaração que recomendava o uso de
result is not None
vs
result != None
Eu queria saber qual é a diferença, e por que um pode ser recomendado em detrimento do outro?
Respostas:
==é um teste de igualdade . Ele verifica se o lado direito e o lado esquerdo são iguais objectos (de acordo com as suas __eq__ou __cmp__métodos.)
isé um teste de identidade . Ele verifica se o lado direito e o lado esquerdo são o mesmo objeto. Nenhuma chamada de método é feita, os objetos não podem influenciar a isoperação.
Você usa is(e is not) para singletons, como None, onde você não se importa com objetos que possam querer fingir estar Noneou onde deseja proteger contra objetos quebrados ao serem comparados None.
Nonetem poucos métodos e quase nenhum atributo. Se o seu __eq__teste esperava um método ou atributo, ele pode quebrar. def __eq__( self, other ): return self.size == other.size. Por exemplo, irá quebrar se otheracontecer None.
isé como o Java ==. O Python ==é como o Java .equals(). Claro que isso só ajuda se você conhece Java.
isé como ===(muito igual) e, inversamente, is noté como !==(não é exatamente igual).
is notum único operador ou está apenas negando o resultado de isgostar internamente not foo is bar?
Primeiro, deixe-me passar por alguns termos. Se você apenas deseja que sua pergunta seja respondida, role para baixo até "Respondendo a sua pergunta".
Identidade do objeto : ao criar um objeto, você pode atribuí-lo a uma variável. Você também pode atribuí-lo a outra variável. E outro.
>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
Neste caso, cancel, close, e dismisstodos se referem ao mesmo objeto na memória. Você criou apenas um Buttonobjeto e todas as três variáveis se referem a esse único objeto. Dizemos que cancel, closee dismisstodos se referem a idênticas objetos; isto é, eles se referem a um único objeto.
Igualdade de objetos : quando você compara dois objetos, geralmente não se importa que se refira exatamente ao mesmo objeto na memória. Com a igualdade de objetos, você pode definir suas próprias regras para comparar dois objetos. Quando você escreve if a == b:, você está dizendo essencialmente if a.__eq__(b):. Isso permite definir um __eq__método ema para que você possa usar sua própria lógica de comparação.
Justificativa: Dois objetos têm exatamente os mesmos dados, mas não são idênticos. (Eles não são o mesmo objeto na memória.) Exemplo: Strings
>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
Nota: Eu uso cadeias unicode aqui porque o Python é inteligente o suficiente para reutilizar cadeias regulares sem criar novas na memória.
Aqui, eu tenho duas cadeias unicode, ae b. Eles têm exatamente o mesmo conteúdo, mas não são o mesmo objeto na memória. No entanto, quando os comparamos, queremos que eles comparem iguais. O que está acontecendo aqui é que o objeto unicode implementou o __eq__método.
class unicode(object):
# ...
def __eq__(self, other):
if len(self) != len(other):
return False
for i, j in zip(self, other):
if i != j:
return False
return True
Nota: __eq__on unicodeé definitivamente implementado com mais eficiência do que isso.
Justificativa: Dois objetos têm dados diferentes, mas são considerados o mesmo objeto se alguns dados importantes forem os mesmos. Exemplo: a maioria dos tipos de dados do modelo
>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True
Aqui, tenho dois monitores Dell ae b. Eles têm a mesma marca e modelo. No entanto, eles não têm os mesmos dados nem o mesmo objeto na memória. No entanto, quando os comparamos, queremos que eles comparem iguais. O que está acontecendo aqui é que o objeto Monitor implementou o __eq__método.
class Monitor(object):
# ...
def __eq__(self, other):
return self.make == other.make and self.model == other.model
Ao comparar com None, use sempreis not . Nenhum é um singleton em Python - existe apenas uma instância na memória.
Comparando a identidade , isso pode ser realizado muito rapidamente. O Python verifica se o objeto ao qual você está se referindo tem o mesmo endereço de memória que o objeto None global - uma comparação muito, muito rápida de dois números.
Ao comparar a igualdade , o Python precisa verificar se o seu objeto possui um __eq__método. Caso contrário, examina cada superclasse procurando um __eq__método. Se encontrar, Python o chama. Isso é especialmente ruim se o __eq__método for lento e não retornar imediatamente quando perceber que o outro objeto estáNone .
Você não implementou __eq__? Então o Python provavelmente encontrará o __eq__método objecte o utilizará - o que apenas verifica a identidade do objeto de qualquer maneira.
Ao comparar a maioria das outras coisas em Python, você estará usando !=.
Considere o seguinte:
class Bad(object):
def __eq__(self, other):
return True
c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)
Noneé um singleton, portanto, a comparação de identidade sempre funcionará, enquanto um objeto pode falsificar a comparação de igualdade via .__eq__().
None, mas um comportamento incorreto Nonepode ocorrer como um efeito colateral da implementação da igualdade contra outros tipos. Não são tantas implicações de segurança, mas apenas implicações de correção.
>>> () é () Verdade >>> 1 é 1 Verdade >>> (1,) == (1,) Verdade >>> (1,) é (1,) Falso >>> a = (1,) >>> b = a >>> a é b Verdade
Alguns objetos são singletons e, portanto, iscom eles é equivalente a ==. A maioria não é.
()e 1não são inerentemente singletons.
-NSMALLNEGINTS <= n <= NSMALLPOSINTS) e as tuplas vazias são singletons. Na verdade, não está documentado nem garantido, mas é improvável que mude.