Qu'est-ce qu'une valeur None?

130

J'ai étudié Python et j'ai lu un chapitre qui décrit la Nonevaleur, mais malheureusement, ce livre n'est pas très clair à certains moments. J'ai pensé que je trouverais la réponse à ma question, si je la partage là-bas.

Je veux savoir ce que la Nonevaleur est et ce que l' utilisez - vous pour?

Et aussi, je ne comprends pas cette partie du livre:

Attribuer une valeur de Noneà une variable est un moyen de la réinitialiser à son état vide d'origine.

Qu'est-ce que ça veut dire?

Les réponses étaient excellentes, même si je n'ai pas compris la plupart des réponses en raison de ma faible connaissance du monde informatique (je n'ai pas appris sur les classes, les objets, etc.). Qu'est-ce que cette phrase veut dire?

Attribuer une valeur de Noneà une variable est un moyen de la réinitialiser à son état vide d'origine.

Final:

Enfin, j'ai ma réponse en regardant différentes réponses. Je dois apprécier toutes les personnes qui mettent leur temps à m'aider (en particulier Martijn Pieters et DSM), et j'aimerais pouvoir choisir toutes les réponses comme étant les meilleures, mais la sélection est limitée à une. Toutes les réponses étaient excellentes.

The_Diver
la source
39
Ce livre n'est pas très utile; Nonen'est pas un état vide par défaut pour les variables.
Martijn Pieters
Le php est le seul langage dont la valeur nulle est équivalente à l'état vide par défaut d'une variable. Maintenant, je me demande quelles autres langues font cela.
kojiro
@kojiro perl, bien qu'aucun des opérateurs d'égalité ne se contente de comparer avec undef. aussi sans doute javascript, bien qu'il ait à la fois nullet undefined.
Evoli
La valeur par défaut de la variable javascript @kojiro est undefined, si elle n'est pas initialisée.
thefourtheye
Bien, ce qui est différent d' nullun point que je ne parviens pas à faire valoir à @MartijnPieters dans sa réponse.
kojiro

Réponses:

99

La réponse de Martijn explique ce qu'il Noney a en Python et déclare correctement que le livre est trompeur. Puisque les programmeurs Python en règle générale ne diraient jamais

Attribuer une valeur de Noneà une variable est un moyen de la réinitialiser à son état vide d'origine.

il est difficile d'expliquer ce que Briggs signifie d'une manière qui a du sens et explique pourquoi personne ici ne semble satisfait de cela. Une analogie qui peut aider:

En Python, les noms de variables sont comme des autocollants placés sur des objets. Chaque autocollant a un nom unique écrit dessus, et il ne peut être que sur un objet à la fois, mais vous pouvez mettre plus d'un autocollant sur le même objet, si vous le souhaitez. Quand tu écris

F = "fork"

vous mettez l'autocollant "F" sur un objet string "fork". Si vous écrivez ensuite

F = None

vous déplacez l'autocollant sur l' Noneobjet.

Ce que Briggs vous demande d'imaginer, c'est que vous n'avez pas écrit l'autocollant "F", il y avait déjà un Fautocollant sur le None, et tout ce que vous avez fait a été de le déplacer , de Noneà "fork". Ainsi, lorsque vous tapez F = None, vous le «remettez [ting] à son état vide d'origine», si nous décidons de le traiter Nonecomme un sens empty state.

Je peux voir ce qu'il veut, mais c'est une mauvaise façon de voir les choses. Si vous démarrez Python et tapez print(F), vous voyez

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

et cela NameErrorsignifie que Python ne reconnaît pas le nom F, car un tel autocollant n'existe pas . Si Briggs avait raison et se F = Noneréinitialise Fà son état d'origine, alors il devrait être là maintenant, et nous devrions voir

>>> print(F)
None

comme nous le faisons après avoir tapé F = Noneet mis l'autocollant None.


C'est donc tout ce qui se passe. En réalité, Python est livré avec des autocollants déjà attachés aux objets (noms intégrés), mais d'autres, vous devez vous écrire avec des lignes comme F = "fork"et A = 2et c17 = 3.14, puis vous pouvez les coller sur d'autres objets plus tard (comme F = 10ou F = None; c'est tout de même .)

Briggs prétend que tous les autocollants possibles que vous pourriez vouloir écrire étaient déjà collés à l' Noneobjet.

DSM
la source
1
désolé mais qu'entendez-vous par Briggs? Faites-vous référence à l'auteur de ce livre? parce que son nom est Jason R. Briggs.
The_Diver
@The_Diver: oui, c'est lui.
DSM
Où puis-je trouver plus d'informations sur les noms intégrés de Python? Merci.
The_Diver
3
C'est une excellente explication pour un non-programmeur. Merci beaucoup!
Christina le
67

Noneest juste une valeur couramment utilisée pour signifier «vide» ou «aucune valeur ici». C'est un objet signal ; il n'a de sens que parce que la documentation Python dit qu'il a cette signification.

Il n'y a qu'une seule copie de cet objet dans une session d'interpréteur Python donnée.

Si vous écrivez une fonction et que cette fonction n'utilise pas d' returninstruction explicite , elle Noneest renvoyée à la place, par exemple. De cette façon, la programmation avec des fonctions est beaucoup plus simple; une fonction renvoie toujours quelque chose , même si ce n'est que cet Noneobjet.

Vous pouvez le tester explicitement:

if foo is None:
    # foo is set to None

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

Une autre utilisation est de donner aux fonctions des paramètres optionnels par défaut 'vide':

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

La fonction spam()a un argument facultatif; si vous appelez spam()sans le spécifier, la valeur par défaut Nonelui est donnée, ce qui permet de détecter facilement si la fonction a été appelée avec un argument ou non.

D'autres langues ont des concepts similaires. SQL a NULL; JavaScript a undefined et null , etc.

Notez qu'en Python, les variables existent parce qu'elles sont utilisées. Vous n'avez pas besoin de déclarer une variable au préalable, il n'y a donc pas de variables vraiment vides en Python. Définir une variable sur Nonen'est alors pas la même chose que la définir sur une valeur vide par défaut; Noneest également une valeur, même si elle est souvent utilisée pour signaler le vide. Le livre que vous lisez est trompeur sur ce point.

Martijn Pieters
la source
1
Je pense que la sémantique de la vacuité est différente de celle de l' indéfini . Je ne suis donc pas sûr que les homologues JavaScript et SQL clarifient - ils peuvent confondre le problème. JavaScript a à la fois undefined et null .
kojiro
@kojiro: undefinedest un objet en JavaScript, et vous pouvez utiliser cet objet explicitement comme vous pouvez l'utiliser Noneen Python. C'est un objet signal, avec à peu près la même signification.
Martijn Pieters
@kojiro: SQL n'est pas un langage de programmation, mais NULLc'est toujours quelque chose qui peut être assigné et testé explicitement.
Martijn Pieters
5
@MartijnPieters: SQL est un langage de programmation, juste un but très spécifique, déclaratif.
danielkza
3
@daniel: savoir si SQL est qualifié de langage de programmation a été un long débat ... Voir stackoverflow.com/questions/900055/… pour des angles intéressants.
Martijn Pieters
23

Voici ce que la documentation Python a à dire sur None:

La seule valeur de types.NoneType. Aucun est fréquemment utilisé pour représenter l'absence d'une valeur, comme lorsque les arguments par défaut ne sont pas passés à une fonction.

Modifié dans la version 2.4: les affectations à None sont illégales et déclenchent une SyntaxError.

Remarque Les noms None et debug ne peuvent pas être réaffectés (leurs affectations, même en tant que nom d'attribut, déclenchent SyntaxError), donc ils peuvent être considérés comme des constantes «vraies».

  1. Confirmons le type de Nonepremier

    print type(None)
    print None.__class__

    Production

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

Au fond, NoneTypeest un type de données comme int, floatetc. Vous pouvez consulter la liste des types par défaut disponible en Python 8,15. types - Noms des types intégrés .

  1. Et, Noneest une instance de NoneTypeclasse. Nous pourrions donc vouloir créer des instances de Nonenous - mêmes. Essayons ça

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

    Production

    0
    TypeError: cannot create 'NoneType' instances

Si clairement, ne peut pas créer d' NoneTypeinstances. Nous n'avons pas à nous soucier de l'unicité de la valeur None.

  1. Vérifions comment nous avons mis en œuvre en Noneinterne.

    print dir(None)

    Production

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

Sauf que __setattr__tous les autres sont des attributs en lecture seule. Il n'y a donc aucun moyen de modifier les attributs de None.

  1. Essayons d'ajouter de nouveaux attributs à None

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

    Production

    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'

Les instructions vues ci-dessus produisent respectivement ces messages d'erreur. Cela signifie que nous ne pouvons pas créer d'attributs dynamiquement sur une Noneinstance.

  1. Voyons ce qui se passe lorsque nous attribuons quelque chose None. Selon la documentation, il devrait lancer un fichier SyntaxError. Cela signifie que si nous attribuons quelque chose à None, le programme ne sera pas exécuté du tout.

    None = 1

    Production

    SyntaxError: cannot assign to None

Nous avons établi que

  1. None est une instance de NoneType
  2. None ne peut pas avoir de nouveaux attributs
  3. Les attributs existants de Nonene peuvent pas être modifiés.
  4. Nous ne pouvons pas créer d'autres instances de NoneType
  5. Nous ne pouvons même pas changer la référence Noneen lui attribuant des valeurs.

Ainsi, comme mentionné dans la documentation, Nonepeut vraiment être considéré comme un fichier true constant.

Heureux de savoir None:)

thefourtheye
la source
Très très intéressant !! un doute à quoi sert __setattr__pour None
Grijesh Chauhan
9

Le livre auquel vous faites référence essaie clairement de simplifier considérablement le sens de None. Les variables Python n'ont un état initial, vide - les variables Python sont liées (seulement) quand ils sont définis . Vous ne pouvez pas créer une variable Python sans lui donner une valeur.

>>> 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

mais parfois vous voulez faire en sorte qu'une fonction ait une signification différente selon qu'une variable est définie ou non. Vous pouvez créer un argument avec une valeur par défaut de None:

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

Le fait que cette valeur soit la Nonevaleur spéciale n'est pas très important dans ce cas. J'aurais pu utiliser n'importe quelle valeur par défaut:

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

… Mais avoir Noneautour nous donne deux avantages:

  1. Nous n'avons pas à choisir une valeur spéciale comme -1dont la signification n'est pas claire, et
  2. Notre fonction peut en fait devoir être gérée -1comme une entrée normale.
>>> test(-1)
no x here

Oups!

Donc, le livre est un peu trompeur principalement dans son utilisation du mot reset - attribuer Noneà un nom est un signal à un programmeur que cette valeur n'est pas utilisée ou que la fonction doit se comporter d'une manière par défaut, mais pour réinitialiser une valeur dans son état d'origine non défini, vous devez utiliser le delmot - clé:

>>> 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
la source
5

D'autres réponses ont déjà expliqué magnifiquement la signification de None . Cependant, je voudrais encore jeter plus de lumière sur cela en utilisant un exemple.

Exemple:

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

Maintenant, essayez de deviner la sortie de la liste ci-dessus. Eh bien, la réponse est étonnamment comme ci-dessous:

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

Mais pourquoi?

Beaucoup s'attendront à tort à ce que list1 soit égal à [10] et list3 à ['a'] , pensant que l'argument de la liste sera mis à sa valeur par défaut de [] chaque fois que extendList est appelé.

Cependant, ce qui se passe réellement est que la nouvelle liste par défaut est créée une seule fois lorsque la fonction est définie , et cette même liste est ensuite utilisée par la suite chaque fois que extendList est invoqué sans qu'un argument de liste ne soit spécifié. En effet, les expressions dans les arguments par défaut sont calculées lorsque la fonction est définie, pas lorsqu'elle est appelée .

list1 et list3 fonctionnent donc sur la même liste par défaut, tandis que list2 opère sur une liste séparée qu'elle a créée (en passant sa propre liste vide comme valeur du paramètre de liste).


'Aucun' le sauveur: (Modifiez l'exemple ci-dessus pour produire le comportement souhaité)

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

Avec cette mise en œuvre révisée, le résultat serait:

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

Remarque - Exemple de crédit à toptal.com

Jadav Bheda
la source
3

None est un objet singleton (ce qui signifie qu'il n'y a qu'un seul None), utilisé à de nombreux endroits dans le langage et la bibliothèque pour représenter l'absence d'une autre valeur.


Par exemple:
si dest un dictionnaire, d.get(k)retournera d[k]s'il existe, mais Nonesi dn'a pas de clé k.

Lisez ces informations sur un excellent blog: http://python-history.blogspot.in/

GrvTyagi
la source
3

Toutes ces réponses sont de bonnes réponses, mais je pense qu'il y a plus à expliquer pourquoi Noneest utile.

Imaginez que vous collectiez des RSVP pour un mariage. Vous voulez enregistrer si chaque personne sera présente. S'ils sont présents, vous définissez person.attending = True. S'ils ne sont pas présents, vous définissez person.attending = False. Si vous n'avez reçu aucun RSVP, alors person.attending = None. De cette façon, vous pouvez faire la distinction entre aucune information - None- et une réponse négative.

Dab Brill
la source
1

J'adore les exemples de code (ainsi que les fruits), alors laissez-moi vous montrer

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

Aucun ne veut rien dire, cela n'a aucune valeur.

Aucun est évalué à False.

Azeirah
la source
8
print(None)impressions .. None. Il ne pas , comme vous le suggérez, rien d'impression.
Martijn Pieters
le REPL n'affiche rien Nonesi c'est le résultat de la dernière expression. (ce qui est surtout utile pour les fonctions qui ne sont pas destinées à renvoyer une valeur.)
Evoli
Eugh, mon erreur, j'utilisais IDLE et j'ai supposé qu'il imprimait des variables, apparemment il utilise repl. J'utilise actuellement SO pour perfectionner mes propres compétences en lecture et compréhension de python / javascript / code, donc je fais quelques erreurs :(
Azeirah
2
IDLE, comme l'invite de l'interpréteur interactif Python, masque explicitement Nonesi cela est le résultat d'une expression, principalement pour ne pas encombrer la sortie.
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
la source