Eu posso usar:
if A:
ao invés de
if A is not None:
O último parece tão detalhado. Existe alguma diferença?
A declaração
if A:
chamará A.__nonzero__()
(consulte a documentação sobre nomes de métodos especiais ) e usará o valor de retorno dessa função. Aqui está o resumo:
object.__nonzero__(self)
Chamado para implementar o teste de valor de verdade e a operação interna
bool()
; deve retornarFalse
ouTrue
, ou seus equivalentes inteiros0
ou1
. Quando esse método não é definido,__len__()
é chamado, se definido, e o objeto é considerado verdadeiro se o resultado for diferente de zero. Se uma classe não define nem__len__()
nem__nonzero__()
, todas as suas instâncias são consideradas verdadeiras.
Por outro lado,
if A is not None:
compara única referência A
com None
para ver se ele é o mesmo ou não.
A is not None
é mais rápido, pois há muito menos trabalho a ser feito #if object(): pass
é de ~ 0,130 usec por loop, enquantoif object() is not None: pass
é de ~ 0,135 usec. De qualquer forma, você não deve usar o desempenho para escolher entre esses dois, mas observe as diferenças em como elas funcionam, uma vez que não são equivalentes .if A is not None
parece ser mais lento porque é uma comparação e precisa carregar o singleton internoNone
como uma etapa intermediária para compararA
(dê uma olhada nodis.dis()
). Corrija-me se estiver errado, masif A:
parece ser mais eficiente, assim que você realmente quiser testar o valor da verdade e não aNone
identidade.python -m timeit -s"a=0" "if a: pass" "else: pass"
é mais rápido do que,python -m timeit -s"a=0" "if a is None: pass" "else: pass"
maspython -m timeit -s"a=1" "if a: pass" "else: pass"
é mais lento. Pode ser dependente da plataforma, veja se você obtém os mesmos resultadosis None
teste foi realmente o mais lento para mim. Em PyPy todos eles mediram exatamente o mesmo :)Conforme escrito em PEP8 :
fonte
None
, mas apenas pela verificação do valor de verdade. Nesse caso,if A:
parece mais eficiente (por exemplodis.dis()
, a , existem etapas extras para carregar o built-inNone
e comparar, comif A is not None:
, enquanto há apenas umjump_if
no outro caso).então não é o mesmo que
fonte
Muitas funções retornam None se não houver resultados apropriados. Por exemplo, uma consulta SQLAlchemy
.first()
método de retorna None se não houver linhas no resultado. Suponha que você esteja selecionando um valor que possa retornar 0 e precise saber se é realmente 0 ou se a consulta não teve resultados.Um idioma comum é fornecer ao argumento opcional de uma função ou método o valor padrão de Nenhum e, em seguida, testar esse valor como Nenhum para ver se ele foi especificado. Por exemplo:
compare isso com:
Neste último caso, o que acontece se você ligar
spam(0)
ouspam([])
? A função detectaria (incorretamente) que você não havia passado um valor paraeggs
e calcularia um valor padrão para você. Provavelmente não é isso que você deseja.Ou imagine um método como "retornar a lista de transações para uma determinada conta". Se a conta não existir, ela poderá retornar Nenhuma. Isso é diferente de retornar uma lista vazia (o que significa "esta conta existe, mas não registrou transações).
Finalmente, de volta ao material do banco de dados. Há uma grande diferença entre NULL e uma string vazia. Uma string vazia normalmente diz "há um valor aqui e esse valor não é nada". NULL diz "este valor não foi inserido".
Em cada um desses casos, você deseja usar
if A is None
. Você está verificando um valor específico - Nenhum - não apenas "qualquer valor que seja convertido em Falso".fonte
Eles fazem coisas muito diferentes .
Os cheques abaixo se A tem nada, exceto os valores
False
,[]
,None
,''
e0
. Verifica o valor de A.O abaixo verifica se A é um objeto diferente de Nenhum. Ele verifica e compara a referência (endereço de memória) de A e Nenhum.
UPDATE: Mais explicações
Muitas vezes os dois parecem fazer a mesma coisa, então muitas pessoas os usam de forma intercambiável - é uma péssima ideia. A razão pela qual os dois dão os mesmos resultados é muitas vezes por pura coincidência devido a otimizações do intérprete / compilador, como internamento ou outra coisa.
Com essas otimizações em mente, números inteiros e seqüências de caracteres do mesmo valor acabam usando o mesmo espaço de memória. Isso provavelmente explica por que duas seqüências separadas agem como se fossem iguais.
Outras coisas não se comportam da mesma maneira ..
As duas listas claramente têm sua própria memória. Surpreendentemente, tuplas se comportam como cordas.
Provavelmente, isso porque as tuplas têm a garantia de não mudar, portanto, faz sentido reutilizar a mesma memória.
A conclusão é que você não pode confiar em coincidências . Só porque grasna como um pato, isso não significa que é um pato. Use
is
e==
dependendo do que você realmente deseja verificar. Essas coisas podem ser difíceis de depurar, uma vez que seis
lê como prosa que geralmente apenas examinamos.fonte
None
é um singleton, não é um detalhe de implementação (ao contrário de int ou string interning). Não tenho certeza se sigo o que você quer dizer.None
se comporte de maneira diferenteint
oustr
devido à internação. Meu ponto é queis
e==
estão verificando coisas diferentes; primeiro verifica um endereço de memória, o segundo verifica o conteúdo dos endereços de memória.if A:
será falso se A for 0, Falso, sequência vazia, lista vazia ou Nenhum, o que pode levar a resultados indesejados.fonte
A maioria dos guias que vi sugerem que você deveria usar
se um:
a menos que você tenha um motivo para ser mais específico.
Existem algumas pequenas diferenças. Existem valores diferentes de None que retornam False, por exemplo, listas vazias ou 0, então pense no que você está realmente testando.
fonte
Nenhum é um valor especial no Python que geralmente designa uma variável não inicializada. Para testar se A não possui esse valor específico, use:
Os valores de Falsey são uma classe especial de objetos em Python (por exemplo, false, []). Para testar se A é falsey, use:
Assim, as duas expressões não são as mesmas e é melhor não tratá-las como sinônimos.
PS Nenhum também é falsey, então a primeira expressão implica a segunda. Mas o segundo abrange outros valores falsey além de None. Agora ... se você tiver certeza de que não pode ter outros valores de falsey além de Nenhum em A, poderá substituir a primeira expressão pela segunda.
fonte
Depende do contexto.
Uso
if A:
quando esperoA
que seja algum tipo de coleção e só quero executar o bloco se a coleção não estiver vazia. Isso permite que o chamador passe qualquer coleção bem-comportada, vazia ou não, e faça com que eu faça o que eu espero. Também permiteNone
eFalse
suprime a execução do bloco, o que é ocasionalmente conveniente para chamar código.OTOH, se eu espero
A
que seja algum objeto completamente arbitrário, mas poderia ter sido padronizadoNone
, eu sempre o usoif A is not None
, pois o código de chamada pode ter passado deliberadamente uma referência a uma coleção vazia, cadeia vazia ou um tipo numérico com valor 0 ou boleanoFalse
ou alguma instância de classe que seja falsa no contexto booleano.E, por outro lado, se eu espero
A
ser algo mais específico (por exemplo, instância de uma classe da qual chamarei métodos), mas poderia ter sido o padrãoNone
, e considero a conversão booleana padrão uma propriedade da classe Não me importo de impor todas as subclasses, então usareiif A:
para poupar meus dedos o terrível fardo de digitar 12 caracteres extras.fonte
Criei um arquivo chamado
test.py
e o executei no intérprete. Você pode mudar o que quiser, para testar com certeza como as coisas estão acontecendo nos bastidores.Esta é a diferença do assembler:
Fonte:
fonte
O primeiro é mais Pythonic (melhor código ideomatic), mas não executará o bloco se A for False (not None).
fonte
is/is not None
. Após PEP8 é Pythonic. Além dos dois testes são diferentes .python> = 2.6,
se escrevermos como
irá gerar um aviso como,
Para que possamos usar
fonte