Existe alguma diferença entre “foo is None” e “foo == None”?
-
09-06-2019 - |
Pergunta
Existe alguma diferença entre:
if foo is None: pass
e
if foo == None: pass
A convenção que vi na maioria dos códigos Python (e no código que eu mesmo escrevo) é a primeira, mas recentemente me deparei com um código que usa a última.None é uma instância (e a única instância, IIRC) de NoneType, então não deveria importar, certo?Há alguma circunstância em que isso possa acontecer?
Solução
is
sempre retorna True
se comparar a mesma instância do objeto
Enquanto ==
é finalmente determinado pelo __eq__()
método
ou seja
>>> class Foo(object):
def __eq__(self, other):
return True
>>> f = Foo()
>>> f == None
True
>>> f is None
False
Outras dicas
Você pode querer ler isso identidade e equivalência de objeto.
A instrução 'is' é usada para identidade do objeto, ela verifica se os objetos se referem à mesma instância (mesmo endereço na memória).
E a declaração '==' refere-se à igualdade (mesmo valor).
Uma palavra de cautela:
if foo:
# do something
É não Exatamente o mesmo que:
if x is not None:
# do something
O primeiro é um teste de valor booleano e pode ser avaliado como falso em diferentes contextos.Há uma série de coisas que representam falso em testes de valor booleano, por exemplo, contêineres vazios, valores booleanos.Nenhum também é avaliado como falso nesta situação, mas outras coisas também o são.
(ob1 is ob2)
igual a (id(ob1) == id(ob2))
A razão foo is None
é a maneira preferida é que você esteja manipulando um objeto que define seu próprio __eq__
, e isso define o objeto como igual a None.Então, use sempre foo is None
se você precisa ver se é de fato None
.
Não há diferença porque objetos idênticos serão naturalmente iguais.No entanto, PEP 8 afirma claramente que você deve usar is
:
Comparações com singletons como None devem sempre ser feitas com is ou not is, nunca com os operadores de igualdade.
is
testes de identidade, não igualdade.Para sua declaração foo is none
, Python simplesmente compara o endereço de memória dos objetos.Isso significa que você está fazendo a pergunta "Tenho dois nomes para o mesmo objeto?"
==
por outro lado, testes de igualdade, conforme determinado pelo __eq__()
método.Não se importa com identidade.
In [102]: x, y, z = 2, 2, 2.0
In [103]: id(x), id(y), id(z)
Out[103]: (38641984, 38641984, 48420880)
In [104]: x is y
Out[104]: True
In [105]: x == y
Out[105]: True
In [106]: x is z
Out[106]: False
In [107]: x == z
Out[107]: True
None
é um operador singleton.Então None is None
é sempre verdade.
In [101]: None is None
Out[101]: True
Para None não deveria haver diferença entre igualdade (==) e identidade (é).O NoneType provavelmente retorna identidade para igualdade.Como None é a única instância que você pode fazer de NoneType (acho que isso é verdade), as duas operações são iguais.No caso de outros tipos, nem sempre é esse o caso.Por exemplo:
list1 = [1, 2, 3]
list2 = [1, 2, 3]
if list1==list2: print "Equal"
if list1 is list2: print "Same"
Isso imprimiria "Igual", pois as listas possuem uma operação de comparação que não é o retorno padrão da identidade.
@Jasão:
Eu recomendo usar algo mais parecido com
if foo: #foo isn't None else: #foo is None
Não gosto de usar "if foo:" a menos que foo realmente represente um valor booleano (ou seja,0 ou 1).Se foo for uma string ou um objeto ou qualquer outra coisa, "if foo:" pode funcionar, mas parece um atalho preguiçoso para mim.Se você estiver verificando se x é Nenhum, diga "se x é Nenhum:".
Mais alguns detalhes:
O
is
cláusula realmente verifica se os doisobject
S estão no mesmo local de memória ou não.ou seja, se ambos apontam para o mesmo local de memória e têm o mesmoid
.Como consequência de 1,
is
garante se, ou não, os dois representados lexicamenteobject
s têm atributos idênticos (atributos-de-atributos...) ou nãoInstanciação de tipos primitivos como
bool
,int
,string
(com algumas exceções),NoneType
ter o mesmo valor estará sempre no mesmo local de memória.
Por exemplo.
>>> int(1) is int(1)
True
>>> str("abcd") is str("abcd")
True
>>> bool(1) is bool(2)
True
>>> bool(0) is bool(0)
True
>>> bool(0)
False
>>> bool(1)
True
E desde NoneType
só pode ter uma instância de si mesmo na tabela de "pesquisa" do python, portanto, o primeiro e o último são mais um estilo de programação do desenvolvedor que escreveu o código (talvez para consistência) em vez de ter qualquer razão lógica sutil para escolher um sobre o outro.
A conclusão de John Machin de que None
é um singleton é uma conclusão reforçada por este código.
>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>>
Desde None
é um singleton, x == None
e x is None
teria o mesmo resultado.No entanto, na minha opinião estética, x == None
é melhor.
a is b # returns true if they a and b are true alias
a == b # returns true if they are true alias or they have values that are deemed equivalence
a = [1,3,4]
b = a[:] #creating copy of list
a is b # if gives false
False
a == b # gives true
True