Geralmente, 'someobj is None' é preferível a 'someobj == None' #
Aaron Maenpaa 20/09/08
e o pseudocódigo se X não for Nenhum? Ou X != None?
Charlie Parker
esta pergunta é mais detalhada do que as outras ... parabéns ...
alamin
Respostas:
187
No primeiro teste, o Python tenta converter o objeto em um boolvalor, caso ainda não o seja. A grosso modo, estamos perguntando o objeto: você é significativo ou não? Isso é feito usando o seguinte algoritmo:
Se o objeto tiver um __nonzero__método especial (assim como os embutidos numéricos inte float), ele chamará esse método. Ele deve retornar um boolvalor que é então usado diretamente ou um intvalor que é considerado Falseigual a zero.
Caso contrário, se o objeto tem um __len__método especial (como fazem recipiente built-ins, list, dict, set, tuple, ...), ele chama esse método, considerando um recipiente Falsese ela estiver vazia (comprimento é zero).
Caso contrário, o objeto será considerado, a Truemenos que None, nesse caso, seja considerado False.
No segundo teste, o objeto é comparado para igualdade com None. Aqui, estamos perguntando ao objeto: "Você é igual a esse outro valor?" Isso é feito usando o seguinte algoritmo:
Se o objeto tiver um __eq__método, ele será chamado e o valor de retorno será convertido em um boolvalor e usado para determinar o resultado de if.
Caso contrário, se o objeto tiver um __cmp__método, ele será chamado. Esta função deve retornar um intindicando a ordem dos dois objetos ( -1se self < other, 0se self == other, +1se self > other).
Caso contrário, o objeto é comparado à identidade (ou seja, é referência ao mesmo objeto, como pode ser testado pelo isoperador).
É possível outro teste usando o isoperador. Nós estaríamos perguntando ao objeto: "Você é esse objeto em particular?"
Geralmente, eu recomendaria usar o primeiro teste com valores não numéricos, usar o teste de igualdade quando desejar comparar objetos da mesma natureza (duas cadeias, dois números, ...) e verificar a identidade apenas quando usando valores sentinela ( Noneou seja, não inicializado para um campo de membro por exemplo, ou ao usar getattros __getitem__métodos ou ).
Embora tecnicamente correto, isso não explica que tuplas, listas, dictos, strs, unicodes, ints, floats etc. têm um diferente de zero . É muito mais comum confiar no valor verdadeiro do tipo interno do que confiar em um método diferente de zero personalizado .
Ddaa 19/09/08
50
Na verdade, essas são duas práticas ruins. Era uma vez, considerado OK tratar casualmente Nenhum e Falso como semelhantes. No entanto, desde o Python 2.2, essa não é a melhor política.
Primeiro, quando você faz um if xou if not xtipo de teste, o Python precisa converter implicitamente xem booleano. As regras para a boolfunção descrevem uma série de coisas que são falsas; tudo o resto é verdadeiro. Se o valor de x não era propriamente booleano, essa conversão implícita não é realmente a maneira mais clara de dizer as coisas.
Antes do Python 2.2, não havia função bool, portanto era ainda menos clara.
Segundo, você realmente não deveria testar == None. Você deve usar is Nonee is not None.
-Comparisons to singletons like None should always be done with'is'or'is not', never the equality operators.Also, beware of writing "if x" when you really mean "if x is not None"-- e.g. when testing whether a variable or argument that defaults to
None was set to some other value.The other value might have a type
(such as a container) that could be false in a boolean context!
Quantos singletons existem? Cinco: None, True, False, NotImplementede Ellipsis. Já que é improvável que você use NotImplementedou Ellipsisnunca diria if x is True(porque simplesmente if xé muito mais claro), você só testará None.
A segunda forma é categoricamente não uma prática ruim. O PEP 8 recomenda o uso de se x duas vezes . Primeiro para sequências (em vez de usar len) e depois para Verdadeiro e Falso (em vez de usar é). Praticamente todo o código Python que eu vi usa se x e se não x.
Antti Rasinen 19/09/08
35
Porque Nonenão é a única coisa que é considerada falsa.
ifnotFalse:print"False is false."ifnot0:print"0 is false."ifnot[]:print"An empty list is false."ifnot():print"An empty tuple is false."ifnot{}:print"An empty dict is false."ifnot"":print"An empty string is false."
False, 0, (), [], {}E ""são todos diferentes None, para que seus dois trechos de código são não equivalente.
Além disso, considere o seguinte:
>>>False==0True>>>False==()False
if object:não é uma verificação de igualdade. 0, (), [], None, {}, Etc. são todos diferentes uns dos outros, mas todos eles avaliar a False.
Esta é a "mágica" por trás de expressões de curto-circuito como:
Em relação à sua última pergunta, eles são equivalentes.
Sylvain Defresne 19/09/08
E ambos incorretos porque "" é falso. O segundo deve ler '("",) ou ("s",)'. De qualquer forma, as versões modernas do python têm um operador ternário adequado. Este hack propenso a erros deve ser banido.
o método __nonzero__ de spam é chamado. No manual do Python:
__nonzero__ ( self ) Chamado para implementar testes de valor verdade e a operação interna bool (); deve retornar False ou True, ou seus equivalentes inteiros 0 ou 1. Quando esse método não é definido, __len __ () é chamado, se for definido (veja abaixo). Se uma classe não define __len __ () nem __nonzero __ (), todas as suas instâncias são consideradas verdadeiras.
Se você perguntar
if spam ==None:print"Sorry. No SPAM here either."
o método __eq__ de spam é chamado com o argumento Nenhum .
Essas duas comparações servem a propósitos diferentes. O primeiro verifica o valor booleano de algo, o segundo verifica a identidade com o valor Nenhum.
Para estar absolutamente correto, o segundo verifica a igualdade com o valor Nenhum ... "someobj is None" verifica a identidade.
Matthew Trevor
0
Por um lado, o primeiro exemplo é mais curto e parece melhor. De acordo com os outros posts, o que você escolhe também depende do que você realmente deseja fazer com a comparação.
Pessoalmente, escolhi uma abordagem consistente entre os idiomas: eu faço if (var)(ou equivalente) apenas se var for declarado como booleano (ou definido como tal, em C não temos um tipo específico). Eu prefixo essas variáveis com a b(então seria bVarrealmente) para ter certeza de que não usarei acidentalmente outro tipo aqui.
Eu realmente não gosto de conversão implícita para booleana, menos ainda quando existem inúmeras regras complexas.
Claro, as pessoas vão discordar. Alguns vão além, eu vejo if (bVar == true)no código Java no meu trabalho (redundante demais para o meu gosto!), Outros adoram sintaxe compacta demais, indo while (line = getNextLine())(ambígua demais para mim).
X != None
?Respostas:
No primeiro teste, o Python tenta converter o objeto em um
bool
valor, caso ainda não o seja. A grosso modo, estamos perguntando o objeto: você é significativo ou não? Isso é feito usando o seguinte algoritmo:Se o objeto tiver um
__nonzero__
método especial (assim como os embutidos numéricosint
efloat
), ele chamará esse método. Ele deve retornar umbool
valor que é então usado diretamente ou umint
valor que é consideradoFalse
igual a zero.Caso contrário, se o objeto tem um
__len__
método especial (como fazem recipiente built-ins,list
,dict
,set
,tuple
, ...), ele chama esse método, considerando um recipienteFalse
se ela estiver vazia (comprimento é zero).Caso contrário, o objeto será considerado, a
True
menos queNone
, nesse caso, seja consideradoFalse
.No segundo teste, o objeto é comparado para igualdade com
None
. Aqui, estamos perguntando ao objeto: "Você é igual a esse outro valor?" Isso é feito usando o seguinte algoritmo:Se o objeto tiver um
__eq__
método, ele será chamado e o valor de retorno será convertido em umbool
valor e usado para determinar o resultado deif
.Caso contrário, se o objeto tiver um
__cmp__
método, ele será chamado. Esta função deve retornar umint
indicando a ordem dos dois objetos (-1
seself < other
,0
seself == other
,+1
seself > other
).Caso contrário, o objeto é comparado à identidade (ou seja, é referência ao mesmo objeto, como pode ser testado pelo
is
operador).É possível outro teste usando o
is
operador. Nós estaríamos perguntando ao objeto: "Você é esse objeto em particular?"Geralmente, eu recomendaria usar o primeiro teste com valores não numéricos, usar o teste de igualdade quando desejar comparar objetos da mesma natureza (duas cadeias, dois números, ...) e verificar a identidade apenas quando usando valores sentinela (
None
ou seja, não inicializado para um campo de membro por exemplo, ou ao usargetattr
os__getitem__
métodos ou ).Para resumir, temos:
fonte
Na verdade, essas são duas práticas ruins. Era uma vez, considerado OK tratar casualmente Nenhum e Falso como semelhantes. No entanto, desde o Python 2.2, essa não é a melhor política.
Primeiro, quando você faz um
if x
ouif not x
tipo de teste, o Python precisa converter implicitamentex
em booleano. As regras para abool
função descrevem uma série de coisas que são falsas; tudo o resto é verdadeiro. Se o valor de x não era propriamente booleano, essa conversão implícita não é realmente a maneira mais clara de dizer as coisas.Antes do Python 2.2, não havia função bool, portanto era ainda menos clara.
Segundo, você realmente não deveria testar
== None
. Você deve usaris None
eis not None
.Consulte PEP 8, Guia de estilo para código Python .
Quantos singletons existem? Cinco:
None
,True
,False
,NotImplemented
eEllipsis
. Já que é improvável que você useNotImplemented
ouEllipsis
nunca diriaif x is True
(porque simplesmenteif x
é muito mais claro), você só testaráNone
.fonte
Porque
None
não é a única coisa que é considerada falsa.False
,0
,()
,[]
,{}
E""
são todos diferentesNone
, para que seus dois trechos de código são não equivalente.Além disso, considere o seguinte:
if object:
não é uma verificação de igualdade.0
,()
,[]
,None
,{}
, Etc. são todos diferentes uns dos outros, mas todos eles avaliar a False.Esta é a "mágica" por trás de expressões de curto-circuito como:
que é uma abreviação para:
embora você realmente deva escrever:
fonte
O PEP 8 - Guia de Estilo para Código Python recomenda o uso é ou não, se você estiver testando o None-ness
Por outro lado, se você estiver testando mais do que Nada, deve usar o operador booleano.
fonte
Se você perguntar
o método __nonzero__ de spam é chamado. No manual do Python:
Se você perguntar
o método __eq__ de spam é chamado com o argumento Nenhum .
Para obter mais informações sobre as possibilidades de personalização, consulte a documentação do Python em https://docs.python.org/reference/datamodel.html#basic-customization
fonte
Essas duas comparações servem a propósitos diferentes. O primeiro verifica o valor booleano de algo, o segundo verifica a identidade com o valor Nenhum.
fonte
Por um lado, o primeiro exemplo é mais curto e parece melhor. De acordo com os outros posts, o que você escolhe também depende do que você realmente deseja fazer com a comparação.
fonte
A resposta é "depende".
Eu uso o primeiro exemplo se considerar 0, "", [] e False (lista não exaustiva) como equivalentes a Nenhum neste contexto.
fonte
Pessoalmente, escolhi uma abordagem consistente entre os idiomas: eu faço
if (var)
(ou equivalente) apenas se var for declarado como booleano (ou definido como tal, em C não temos um tipo específico). Eu prefixo essas variáveis com ab
(então seriabVar
realmente) para ter certeza de que não usarei acidentalmente outro tipo aqui.Eu realmente não gosto de conversão implícita para booleana, menos ainda quando existem inúmeras regras complexas.
Claro, as pessoas vão discordar. Alguns vão além, eu vejo
if (bVar == true)
no código Java no meu trabalho (redundante demais para o meu gosto!), Outros adoram sintaxe compacta demais, indowhile (line = getNextLine())
(ambígua demais para mim).fonte