Respostas:
No Python, o objeto 'nulo' é o singleton None
.
A melhor maneira de verificar as coisas para "Noneness" é usar o operador de identidade is
:
if foo is None:
...
None
Nulo do Python?Não existe null
no Python, mas sim None
. Como já foi dito, a maneira mais precisa de testar se algo foi dado None
como valor é usar o is
operador de identidade, que testa se duas variáveis se referem ao mesmo objeto.
>>> foo is None
True
>>> foo = 'bar'
>>> foo is None
False
None
None
é a única instância da classe NoneType
e qualquer tentativa adicional de instanciar essa classe retornará o mesmo objeto, o que cria None
um singleton. Os recém-chegados ao Python costumam ver mensagens de erro que mencionam NoneType
e se perguntam o que é. É minha opinião pessoal que essas mensagens poderiam simplesmente ser mencionadas None
pelo nome porque, como veremos em breve, None
deixa pouco espaço para a ambiguidade. Portanto, se você vir alguma TypeError
mensagem que mencione que NoneType
não pode ou não pode fazer isso, saiba que é simplesmente aquela None
que estava sendo usada de uma maneira que não pode.
Além disso, None
é uma constante interna, assim que você inicia o Python, ele está disponível para uso em qualquer lugar, seja no módulo, na classe ou na função. NoneType
por outro lado, não, você precisa obter uma referência a ele primeiro consultando None
sua classe.
>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType
Você pode verificar None
a singularidade da função de identidade do Python id()
. Retorna o número único atribuído a um objeto, cada objeto possui um. Se o id de duas variáveis for o mesmo, elas apontam de fato para o mesmo objeto.
>>> NoneType = type(None)
>>> id(None)
10748000
>>> my_none = NoneType()
>>> id(my_none)
10748000
>>> another_none = NoneType()
>>> id(another_none)
10748000
>>> def function_that_does_nothing(): pass
>>> return_value = function_that_does_nothing()
>>> id(return_value)
10748000
None
não pode ser substituídoEm uma versão muito mais antiga do Python (anterior à 2.4), era possível reatribuir None
, mas não mais. Nem mesmo como um atributo de classe ou nos limites de uma função.
# In Python 2.7
>>> class SomeClass(object):
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: cannot assign to None
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to None
# In Python 3.5
>>> class SomeClass:
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: invalid syntax
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to keyword
Portanto, é seguro assumir que todas as None
referências são iguais. Não há "costume" None
.
None
uso do is
operadorAo escrever o código, você pode tentar testar o Noneness dessa maneira:
if value==None:
pass
Ou para testar falsidade como esta
if not value:
pass
Você precisa entender as implicações e por que geralmente é uma boa idéia ser explícito.
None
por que fazer isso
value is None
ao invés de
value==None
O primeiro é equivalente a:
id(value)==id(None)
Considerando que a expressão value==None
é de fato aplicada assim
value.__eq__(None)
se o valor realmente for None
, você obterá o que esperava.
>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True
Na maioria dos casos comuns, o resultado será o mesmo, mas o __eq__()
método abre uma porta que anula qualquer garantia de precisão, pois pode ser substituída em uma classe para fornecer um comportamento especial.
Considere esta classe.
>>> class Empty(object):
... def __eq__(self, other):
... return not other
Então você experimenta None
e funciona
>>> empty = Empty()
>>> empty==None
True
Mas também funciona na string vazia
>>> empty==''
True
E ainda
>>> ''==None
False
>>> empty is None
False
None
como um booleanoOs dois testes a seguir
if value:
# do something
if not value:
# do something
são de fato avaliados como
if bool(value):
# do something
if not bool(value):
# do something
None
é um "falsey", significando que, se convertido em um booleano, ele retornará False
e, se aplicado, o not
operador retornará True
. Observe, no entanto, que não é uma propriedade exclusiva None
. Além de False
si mesma, a propriedade é compartilhada por listas vazias, tuplas, conjuntos, dictos, seqüências de caracteres, além de 0 e todos os objetos de classes que implementam o __bool__()
método mágico para retornar False
.
>>> bool(None)
False
>>> not None
True
>>> bool([])
False
>>> not []
True
>>> class MyFalsey(object):
... def __bool__(self):
... return False
>>> f = MyFalsey()
>>> bool(f)
False
>>> not f
True
Portanto, ao testar variáveis da seguinte maneira, fique atento ao que você está incluindo ou excluindo do teste:
def some_function(value=None):
if not value:
value = init_value()
Acima, você quis chamar init_value()
quando o valor está definido especificamente para None
, ou você quis dizer que um valor definido como 0
, ou a sequência vazia ou uma lista vazia também deveria acionar a inicialização. Como eu disse, fique atento. Como geralmente é o caso explícito em Python, é melhor que implícito .
None
na práticaNone
usado como um valor de sinalNone
tem um status especial em Python. É um valor de linha de base favorito, porque muitos algoritmos o tratam como um valor excepcional. Em tais cenários, ele pode ser usado como um sinalizador para sinalizar que uma condição requer algum tratamento especial (como a configuração de um valor padrão).
Você pode atribuir None
aos argumentos de palavra-chave de uma função e testá-la explicitamente.
def my_function(value, param=None):
if param is None:
# do something outrageous!
Você pode retorná-lo como padrão ao tentar acessar o atributo de um objeto e testá-lo explicitamente antes de fazer algo especial.
value = getattr(some_obj, 'some_attribute', None)
if value is None:
# do something spectacular!
Por padrão, o get()
método de um dicionário retorna None
ao tentar acessar uma chave inexistente:
>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True
Se você tentar acessá-lo usando a notação subscrita, um KeyError
será gerado
>>> value = some_dict['foo']
KeyError: 'foo'
Da mesma forma, se você tentar exibir um item não existente
>>> value = some_dict.pop('foo')
KeyError: 'foo'
que você pode suprimir com um valor padrão que geralmente é definido como None
value = some_dict.pop('foo', None)
if value is None:
# booom!
None
usado como sinalizador e valor válidoOs usos descritos acima de None
aplicar quando não é considerado um valor válido, mas mais como um sinal para fazer algo especial. No entanto, há situações em que às vezes é importante saber de onde None
veio, porque, embora seja usado como sinal, também pode fazer parte dos dados.
Quando você consulta um objeto em busca de seu atributo, getattr(some_obj, 'attribute_name', None)
retornando None
, não informa se o atributo que você estava tentando acessar foi definido None
ou se estava totalmente ausente do objeto. A mesma situação ao acessar uma chave de um dicionário como some_dict.get('some_key')
, você não sabe se some_dict['some_key']
está faltando ou se está apenas definido como None
. Se você precisar dessas informações, a maneira usual de lidar com isso é tentar acessar diretamente o atributo ou a chave de dentro de uma try/except
construção:
try:
# equivalent to getattr() without specifying a default
# value = getattr(some_obj, 'some_attribute')
value = some_obj.some_attribute
# now you handle `None` the data here
if value is None:
# do something here because the attribute was set to None
except AttributeError:
# we're now hanling the exceptional situation from here.
# We could assign None as a default value if required.
value = None
# In addition, since we now know that some_obj doesn't have the
# attribute 'some_attribute' we could do something about that.
log_something(some_obj)
Da mesma forma com dict:
try:
value = some_dict['some_key']
if value is None:
# do something here because 'some_key' is set to None
except KeyError:
# set a default
value = None
# and do something because 'some_key' was missing
# from the dict.
log_something(some_dict)
Os dois exemplos acima mostram como lidar com casos de objetos e dicionários, e as funções? A mesma coisa, mas usamos o argumento de palavra-chave double asteriscos para esse fim:
def my_function(**kwargs):
try:
value = kwargs['some_key']
if value is None:
# do something because 'some_key' is explicitly
# set to None
except KeyError:
# we assign the default
value = None
# and since it's not coming from the caller.
log_something('did not receive "some_key"')
None
usado apenas como um valor válidoSe você achar que seu código está repleto de try/except
padrões acima, simplesmente para diferenciar None
sinalizadores e None
dados, basta usar outro valor de teste. Há um padrão em que um valor que fica fora do conjunto de valores válidos é inserido como parte dos dados em uma estrutura de dados e é usado para controlar e testar condições especiais (por exemplo, limites, estado, etc.). Esse valor é chamado de sentinela e pode ser usado da maneira que None
é usado como sinal. É trivial criar um sentinela em Python.
undefined = object()
O undefined
objeto acima é único e não faz muito de nada que possa interessar a um programa; portanto, é um excelente substituto para None
como sinalizador. Algumas advertências se aplicam, mais sobre isso após o código.
Com função
def my_function(value, param1=undefined, param2=undefined):
if param1 is undefined:
# we know nothing was passed to it, not even None
log_something('param1 was missing')
param1 = None
if param2 is undefined:
# we got nothing here either
log_something('param2 was missing')
param2 = None
Com ditado
value = some_dict.get('some_key', undefined)
if value is None:
log_something("'some_key' was set to None")
if value is undefined:
# we know that the dict didn't have 'some_key'
log_something("'some_key' was not set at all")
value = None
Com um objeto
value = getattr(obj, 'some_attribute', undefined)
if value is None:
log_something("'obj.some_attribute' was set to None")
if value is undefined:
# we know that there's no obj.some_attribute
log_something("no 'some_attribute' set on obj")
value = None
Como mencionei anteriormente, as sentinelas personalizadas vêm com algumas ressalvas. Primeiro, não são palavras-chave None
, portanto, o python não as protege. Você pode substituir os itens undefined
acima a qualquer momento, em qualquer lugar do módulo definido, portanto, tenha cuidado com a exposição e uso deles. Em seguida, a instância retornada por object()
não é um singleton, se você fizer essa chamada 10 vezes, obterá 10 objetos diferentes. Finalmente, o uso de um sentinela é altamente idiossincrático. Um sentinela é específico da biblioteca em que é usado e, portanto, seu escopo geralmente deve ser limitado aos internos da biblioteca. Não deve "vazar". O código externo só deve ficar ciente disso, se seu objetivo é estender ou suplementar a API da biblioteca.
Não é chamado nulo como em outros idiomas, mas None
. Sempre há apenas uma instância desse objeto, portanto, você pode verificar a equivalência com x is None
(comparação de identidade) em vez de x == None
, se desejar.
None
. Então todas aquelas pessoas inteligentes que compararam NoneType
triunfarão!
No Python, para representar a ausência de um valor, você pode usar o valor Nenhum ( types.NoneType.None ) para objetos e "" (ou len () == 0 ) para seqüências de caracteres. Portanto:
if yourObject is None: # if yourObject == None:
...
if yourString == "": # if yourString.len() == 0:
...
Com relação à diferença entre "==" e "is", o teste da identidade do objeto usando "==" deve ser suficiente. No entanto, como a operação "is" é definida como a operação de identidade do objeto, provavelmente é mais correto usá-la, em vez de "==". Não tenho certeza se existe mesmo uma diferença de velocidade.
De qualquer forma, você pode dar uma olhada em:
0 == false
retorna true
é porque o double-iguala operador faz Tipo de coerção. Com o operador triple-equal, no entanto, 0 === false
retorna false
, porque 'number' e 'boolean' são tipos diferentes.
true
em condicionais. Em Rust and Go, 0
e false
diferentes tipos que não podem ser comparados para igualdade.
Nulo é um tipo de objeto especial como:
>>>type(None)
<class 'NoneType'>
Você pode verificar se um objeto está na classe 'NoneType':
>>>variable = None
>>>variable is None
True
Mais informações estão disponíveis no Python Docs
Por teste de valor de Verdade , 'None' testa diretamente como FALSE, portanto a expressão mais simples será suficiente:
if not foo:
True
para qualquer valor falso, não apenas None
.
egg is None
sobreegg == None
: O último pode ser sobrecarregado, e é provável que quebrar quando comparando objeto válido com Nenhum (depende de como ele é implementado, mas você não espera que todos a tomar comparações com None em conta, não é?) , enquantois
sempre funciona da mesma maneira.