O que é um valor Nenhum?

130

Eu estudei Python e li um capítulo que descreve o Nonevalor, mas infelizmente este livro não é muito claro em alguns momentos. Eu pensei que encontraria a resposta para minha pergunta, se a compartilhar lá.

Eu quero saber o que o Nonevalor é eo que você usá-lo?

E também, eu não entendo essa parte do livro:

A atribuição de um valor de Nonea uma variável é uma maneira de redefini-la para seu estado vazio original.

O que isso significa?

As respostas foram ótimas, embora eu não tenha entendido a maioria das respostas devido ao meu baixo conhecimento do mundo da computação (não aprendi sobre classes, objetos etc.). O que está frase significa?

A atribuição de um valor de Nonea uma variável é uma maneira de redefini-la para seu estado vazio original.

Final:

Finalmente, recebi minha resposta procurando respostas diferentes. Devo agradecer a todas as pessoas que dedicam seu tempo para me ajudar (especialmente Martijn Pieters e DSM) e gostaria de poder escolher todas as respostas como as melhores, mas a seleção é limitada a uma. Todas as respostas foram ótimas.

The_Diver
fonte
39
Esse livro não é muito útil; Nonenão é um estado vazio padrão para variáveis.
Martijn Pieters
Em cima da minha cabeça php é a única linguagem cujo valor nulo é equivalente ao estado vazio padrão para uma variável. Agora estou me perguntando o que outras línguas fazem isso.
Kojiro #
@kojiro perl, embora nenhum dos operadores de igualdade esteja feliz em comparar com undef. também sem dúvida javascript, embora tenha ambos nulle undefined.
Eevee
O valor padrão da variável javascript @kojiro é undefined, se não for inicializado.
thefourtheye
Certo, o que é diferente de null, um ponto que deixo de mencionar ao @MartijnPieters em sua resposta.
Kojiro #

Respostas:

99

A resposta de Martijn explica o que Noneestá em Python e afirma corretamente que o livro é enganoso. Como os programadores Python, em regra, nunca diriam

A atribuição de um valor de Nonea uma variável é uma maneira de redefini-la para seu estado vazio original.

é difícil explicar o que Briggs quer dizer de uma maneira que faça sentido e explique por que ninguém aqui parece feliz com isso. Uma analogia que pode ajudar:

No Python, nomes de variáveis ​​são como adesivos colocados em objetos. Cada adesivo possui um nome exclusivo, e só pode estar em um objeto por vez, mas você pode colocar mais de um adesivo no mesmo objeto, se desejar. Quando você escreve

F = "fork"

você coloca o adesivo "F" em um objeto de string "fork". Se você escrever

F = None

você move o adesivo para o Noneobjeto.

O que Briggs está pedindo para você imaginar é que você não escreveu o adesivo "F", já havia um Fadesivo no adesivo Nonee tudo o que você fez foi movê- lo, de Nonepara "fork". Então, quando você digita F = None, está "redefinindo-o para seu estado original e vazio", se decidirmos tratar Nonecomo significado empty state.

Eu posso ver o que ele está dizendo, mas essa é uma maneira ruim de ver. Se você iniciar o Python e digitar print(F), verá

>>> print(F)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'F' is not defined

e isso NameErrorsignifica que o Python não reconhece o nome F, porque não existe esse adesivo . Se Briggs estava certo e F = Noneredefiniu Fpara seu estado original, ele deveria estar lá agora, e deveríamos ver

>>> print(F)
None

como fazemos depois de digitar F = Nonee colocar o adesivo None.


Então é isso que está acontecendo. Na realidade, o Python vem com alguns adesivos já anexados aos objetos (nomes embutidos), mas outros você precisa escrever com linhas como F = "fork"e A = 2e c17 = 3.14, e então pode colá-los em outros objetos mais tarde (como F = 10ou F = None; é tudo a mesma coisa) .)

Briggs está fingindo que todos os adesivos possíveis que você pode querer escrever já estavam grudados no Noneobjeto.

DSM
fonte
1
desculpe, mas o que você quer dizer com Briggs? você está se referindo ao autor deste livro? porque o nome dele é Jason R. Briggs.
The_Diver
@ The_Diver: sim, é ele.
DSM
Onde posso encontrar mais informações sobre os nomes incorporados do Python?
precisa saber é o seguinte
3
Esta é uma ótima explicação para um não programador. Muito obrigado!
Christina
67

Noneé apenas um valor que geralmente é usado para significar 'vazio' ou 'sem valor aqui'. É um objeto de sinal ; ele só tem significado porque a documentação do Python diz que tem esse significado.

Há apenas uma cópia desse objeto em uma determinada sessão de intérprete Python.

Se você escrever uma função e essa função não usar uma returndeclaração explícita , Noneserá retornado, por exemplo. Dessa forma, a programação com funções é muito simplificada; uma função sempre retorna algo , mesmo que seja apenas esse Noneobjeto.

Você pode testá-lo explicitamente:

if foo is None:
    # foo is set to None

if bar is not None:
    # bar is set to something *other* than None

Outro uso é fornecer parâmetros opcionais para funções como um padrão 'vazio':

def spam(foo=None):
    if foo is not None:
        # foo was specified, do something clever!

A função spam()tem um argumento opcional; se você chamar spam()sem especificá-lo, o valor padrão Noneserá fornecido, facilitando a detecção se a função foi chamada com um argumento ou não.

Outras línguas têm conceitos semelhantes. SQL tem NULL; JavaScript tem undefined e null etc.

Observe que no Python, existem variáveis ​​em virtude de serem usadas. Você não precisa declarar uma variável primeiro, portanto, não existem variáveis realmente vazias no Python. Definir uma variável como Nonenão é a mesma coisa que configurá-la para um valor vazio padrão; Nonetambém é um valor, embora seja frequentemente usado para sinalizar vazio. O livro que você está lendo é enganoso nesse ponto.

Martijn Pieters
fonte
1
Eu acho que a semântica do vazio é diferente daquela da indefinição . Portanto, não tenho certeza se os equivalentes JavaScript e SQL estão esclarecendo - eles podem confundir o problema. JavaScript tem ambos undefined e null .
Kojiro #
@kojiro: undefinedé um objeto em JavaScript, e você pode usá-lo explicitamente, assim como Noneem Python. É um objeto de sinal, com o mesmo significado.
Martijn Pieters
@kojiro: SQL não é uma linguagem de programação, mas NULLainda é algo que pode ser atribuído e testado explicitamente.
Martijn Pieters
5
@ MartijnPieters: SQL é uma linguagem de programação, apenas uma finalidade muito específica, declarativa.
Danielkza # 20/13
3
@daniel: se o SQL se qualifica como uma linguagem de programação tem sido um longo debate ... Veja stackoverflow.com/questions/900055/… para obter ângulos interessantes.
Martijn Pieters
23

Isto é o que a documentação do Python tem a dizer sobre None:

O único valor de types.NoneType. Nenhum é freqüentemente usado para representar a ausência de um valor, como quando argumentos padrão não são passados ​​para uma função.

Alterado na versão 2.4: as atribuições a None são ilegais e geram um SyntaxError.

Nota Os nomes Nenhum e depuração não podem ser reatribuídos (as atribuições a eles, mesmo como um nome de atributo, aumentam o SyntaxError), para que possam ser consideradas constantes "verdadeiras".

  1. Vamos confirmar o tipo de Noneprimeiro

    print type(None)
    print None.__class__

    Resultado

    <type 'NoneType'>
    <type 'NoneType'>

Basicamente, NoneTypeé um tipo de dados como int, floatetc. Você pode conferir a lista de tipos padrão disponíveis no Python na 8.15. types - Nomes para tipos internos .

  1. E, Noneé uma instância de NoneTypeclasse. Então, podemos querer criar instâncias de Nonenós mesmos. Vamos tentar isso

    print types.IntType()
    print types.NoneType()

    Resultado

    0
    TypeError: cannot create 'NoneType' instances

Tão claramente, não é possível criar NoneTypeinstâncias. Não precisamos nos preocupar com a singularidade do valor None.

  1. Vamos verificar como implementamos Noneinternamente.

    print dir(None)

    Resultado

    ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', 
     '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__',
     '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

Exceto que __setattr__todos os outros são atributos somente leitura. Portanto, não há como alterar os atributos de None.

  1. Vamos tentar adicionar novos atributos ao None

    setattr(types.NoneType, 'somefield', 'somevalue')
    setattr(None, 'somefield', 'somevalue')
    None.somefield = 'somevalue'

    Resultado

    TypeError: can't set attributes of built-in/extension type 'NoneType'
    AttributeError: 'NoneType' object has no attribute 'somefield'
    AttributeError: 'NoneType' object has no attribute 'somefield'

As instruções vistas acima produzem essas mensagens de erro, respectivamente. Isso significa que, não podemos criar atributos dinamicamente em uma Noneinstância.

  1. Vamos verificar o que acontece quando atribuímos algo None. De acordo com a documentação, deve lançar a SyntaxError. Isso significa que, se atribuirmos algo a None, o programa não será executado.

    None = 1

    Resultado

    SyntaxError: cannot assign to None

Nós estabelecemos que

  1. None é uma instância de NoneType
  2. None não pode ter novos atributos
  3. Atributos existentes de Nonenão podem ser alterados.
  4. Não podemos criar outras instâncias de NoneType
  5. Não podemos nem mudar a referência Noneatribuindo valores a ela.

Portanto, como mencionado na documentação, Nonepode realmente ser considerado como um true constant.

Feliz saber None:)

thefourtheye
fonte
Muito muito interessante !! Uma dúvida que é o uso de __setattr__para Nenhum
Grijesh Chauhan
9

O livro a que você se refere está claramente tentando simplificar bastante o significado de None. As variáveis ​​Python não têm um estado vazio inicial - as variáveis ​​Python são vinculadas (apenas) quando definidas . Você não pode criar uma variável Python sem atribuir um valor a ela.

>>> print(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> def test(x):
...   print(x)
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test() takes exactly 1 argument (0 given)
>>> def test():
...   print(x)
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test
NameError: global name 'x' is not defined

mas às vezes você quer fazer uma função significar coisas diferentes, dependendo de uma variável ser definida ou não. Você pode criar um argumento com um valor padrão de None:

>>> def test(x=None):
...   if x is None:
...     print('no x here')
...   else:
...     print(x)
... 
>>> test()
no x here
>>> test('x!')
x!

O fato de esse valor ser o Nonevalor especial não é muito importante nesse caso. Eu poderia ter usado qualquer valor padrão:

>>> def test(x=-1):
...   if x == -1:
...     print('no x here')
...   else:
...     print(x)
... 
>>> test()
no x here
>>> test('x!')
x!

… Mas ter por Noneperto nos dá dois benefícios:

  1. Não precisamos escolher um valor especial, como -1cujo significado não esteja claro, e
  2. Nossa função pode realmente precisar ser tratada -1como uma entrada normal.
>>> test(-1)
no x here

oops!

Portanto, o livro é um pouco enganador principalmente no uso da palavra reset - atribuir Nonea um nome é um sinal para um programador de que esse valor não está sendo usado ou que a função deve se comportar de alguma maneira padrão, mas para redefinir um valor para seu estado original e indefinido, você deve usar a delpalavra-chave:

>>> x = 3
>>> x
3
>>> del x
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
kojiro
fonte
5

Outras respostas já explicaram o significado de Nenhum lindamente. No entanto, eu ainda gostaria de esclarecer isso usando um exemplo.

Exemplo:

def extendList(val, list=[]):
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3

Agora tente adivinhar a saída da lista acima. Bem, a resposta é surpreendentemente como abaixo:

list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']

Mas por que?

Muitos esperam erroneamente que a lista1 seja igual a [10] e a lista3 seja igual a ['a'] , pensando que o argumento da lista será definido com o valor padrão de [] toda vez que o extendedList for chamado.

No entanto, o que realmente acontece é que a nova lista padrão é criada apenas uma vez quando a função é definida e a mesma lista é usada posteriormente sempre que o extendList é chamado sem que um argumento da lista seja especificado. Isso ocorre porque as expressões nos argumentos padrão são calculadas quando a função é definida, não quando é chamada .

list1 e list3 estão, portanto, operando na mesma lista padrão, enquanto list2 está operando em uma lista separada criada (passando sua própria lista vazia como o valor do parâmetro list).


'Nenhum' o salvador: (Modifique o exemplo acima para produzir o comportamento desejado)

def extendList(val, list=None):
    if list is None:
       list = []
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3

Com esta implementação revisada, a saída seria:

list1 = [10]
list2 = [123]
list3 = ['a']

Nota - Exemplo de crédito para toptal.com

Jadav Bheda
fonte
3

Nenhum é um objeto singleton (significando que existe apenas um Nenhum), usado em muitos lugares no idioma e na biblioteca para representar a ausência de algum outro valor.


Por exemplo:
se dfor um dicionário, d.get(k)retornará d[k]se existir, mas Nonese dnão tiver chave k.

Leia essas informações em um ótimo blog: http://python-history.blogspot.in/

GrvTyagi
fonte
3

Todas essas são boas respostas, mas acho que há mais para explicar por que None é útil.

Imagine você coletando RSVPs para um casamento. Você deseja registrar se cada pessoa comparecerá. Se eles estiverem participando, você define person.attending = True. Se eles não estiverem participando do seu conjunto person.attending = False. Se você não recebeu nenhum RSVP, então person.attending = None. Dessa forma, você pode distinguir entre nenhuma informação - None- e uma resposta negativa.

Dab Brill
fonte
1

Eu amo exemplos de código (assim como frutas), então deixe-me mostrar

apple = "apple"
print(apple)
>>> apple
apple = None
print(apple)
>>> None

Nenhum não significa nada, não tem valor.

Nenhum é avaliado como Falso.

Azeirah
fonte
8
print(None)impressões .. None. Ele faz não , como você sugere, imprimir nada.
Martijn Pieters
o REPL só mostra nada Nonese for o resultado da última expressão. (que é principalmente útil para funções não pretende retornar um valor.)
Eevee
Eugh, meu erro, eu estava usando o IDLE e assumi que ele imprimia variáveis, aparentemente ele usa repl. No momento, estou usando o SO para aperfeiçoar minhas próprias habilidades de leitura e compreensão de código python / javascript /, por isso estou cometendo alguns erros :(
Azeirah
2
O IDLE, como o prompt do interpretador interativo do Python, oculta explicitamente Nonese esse é o resultado de uma expressão, principalmente para não confundir a saída.
Martijn Pieters
-5
largest=none
smallest =none 
While True :
          num =raw_input ('enter a number ') 
          if num =="done ": break 
          try :
           inp =int (inp) 
          except:
              Print'Invalid input' 
           if largest is none :
               largest=inp
           elif inp>largest:
                largest =none 
           print 'maximum', largest

          if smallest is none:
               smallest =none
          elif inp<smallest :
               smallest =inp
          print 'minimum', smallest 

print 'maximum, minimum, largest, smallest 
Sree Latha
fonte