299 votes

Comparaison de None en Python : dois-je utiliser "is" ou == ?

Mon éditeur me prévient quand je compare my_var == None mais aucun avertissement lorsque j'utilise my_var is None .

J'ai fait un test dans le shell Python et j'ai déterminé que les deux syntaxes sont valides, mais mon éditeur semble dire que my_var is None est préférable.

Est-ce le cas, et si oui, pourquoi ?

8 votes

PEP 8 indique quelque part que vous devez comparer aux singletons en utilisant is - python.org/dev/peps/pep-0008/#programming-recommendations

2 votes

Ce poster parle de Python 3, et ma question concerne Python 2.x. Je ne suis pas sûr que ce soit une différence assez importante pour justifier les deux restants, mais j'ai édité la question pour l'inclure juste au cas où.

4 votes

Je ne pense pas que cette question soit vraiment un doublon. L'autre portait sur == vs is en général, celle-ci porte sur None en particulier.

348voto

mgilson Points 92954

Résumé :

Utilice is lorsque vous souhaitez vérifier la validité de l'objet. identité (par exemple, en vérifiant si var es None ). Utilisez == lorsque vous voulez vérifier égalité (par exemple, est-ce que var égal à 3 ?).

Explication :

Vous pouvez avoir des classes personnalisées où my_var == None retournera True

par exemple

class Negator(object):
    def __eq__(self,other):
        return not other

thing = Negator()
print thing == None    #True
print thing is None    #False

is vérifie l'objet identité . Il n'y a qu'un seul objet None donc quand vous le faites my_var is None vous vérifiez s'il s'agit bien du même objet (et pas seulement de l'objet équivalent objets)

En d'autres termes, == est une vérification de l'équivalence (qui est définie d'un objet à l'autre) alors que is vérifie l'identité de l'objet :

lst = [1,2,3]
lst == lst[:]  # This is True since the lists are "equivalent"
lst is lst[:]  # This is False since they're actually different objects

0 votes

Voulez-vous dire en surchargeant l'opérateur == pour qu'il renvoie toujours True lorsqu'il est comparé à None ?

45 votes

Quand est-ce que is None diffèrent de == None ?

21 votes

@Blender Dans le cas mentionné. __eq__ peuvent être définis de n'importe quelle manière, mais le comportement de is ne peut pas être changé si facilement.

186voto

user4815162342 Points 27348

is est généralement préférée pour comparer des objets arbitraires à des singletons tels que None parce que c'est plus rapide et plus prévisible. is compare toujours par identité d'objet, alors que ce qui == va faire dépend du type exact des opérandes et même de leur ordre.

Cette recommandation est soutenue par PEP 8 qui indique explicitement que "les comparaisons avec des singletons comme None devraient toujours être faites avec is o is not mais jamais les opérateurs d'égalité."

16 votes

Merci d'avoir publié cet article ; la réponse acceptée présente des points intéressants, mais la vôtre répond à la question de manière beaucoup plus directe.

0 votes

Il semble bizarre de s'appuyer sur ce qui est essentiellement un détail de mise en œuvre. Pourquoi devrais-je me soucier du nombre d'instances de NoneType qui existent ?

1 votes

@BallpointBen Parce que c'est no un détail de mise en œuvre - il n'y a qu'un seul None sous la constante globale None . Si quoi que ce soit, le NoneType est un détail d'implémentation car l None singleton doit avoir un peu de type. (Le fait que vous ne pouvez pas créer d'instances de ce type est une bonne indication que son unique instance est destinée à être un singleton).

12voto

Thorsten Kranz Points 5563

PEP 8 définit qu'il est préférable d'utiliser l'option is lors de la comparaison de singletons.

4voto

Danferno Points 81

J'ai récemment rencontré un cas où cela peut mal tourner.

import numpy as np
nparray = np.arange(4)

# Works
def foo_is(x=None):
    if x is not None:
        print(x[1])

foo_is()
foo_is(nparray)

# Code below raises 
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
def foo_eq(x=None):
    if x != None:
        print(x[1])

foo_eq()
foo_eq(nparray)

J'ai créé une fonction qui prend optionnellement un tableau numpy comme argument et change s'il est inclus. Si je teste son inclusion en utilisant les opérateurs d'inégalité != ce qui soulève une ValueError (voir le code ci-dessus). Si j'utilise is not none le code fonctionne correctement.

-2voto

Arlem Points 11

Un autre exemple où "==" diffère de "est". Lorsque vous extrayez des informations d'une base de données et que vous vérifiez si une valeur existe, le résultat sera soit une valeur, soit Aucune.

Regardez le if et le else ci-dessous. Seul "is" fonctionne lorsque la base de données renvoie "None". Si vous mettez == à la place, l'instruction if ne fonctionnera pas, elle passera directement à else, même si le résultat est "None". J'espère que j'ai été clair.

conn = sqlite3.connect('test.db')
c = conn.cursor()
row = itemID_box.get()

# pull data to be logged so that the deletion is recorded
query = "SELECT itemID, item, description FROM items WHERE itemID LIKE '%" + row + "%'"
c.execute(query)
result = c.fetchone()

if result is None:
    # log the deletion in the app.log file
    logging = logger('Error')
    logging.info(f'The deletion of {row} failed.')
    messagebox.showwarning("Warning", "The record number is invalid")
else:
    # execute the deletion
    c.execute("DELETE from items WHERE itemID = " + row)
    itemID_box.delete(0, tk.END)
    messagebox.showinfo("Warning", "The record has been deleted")
    conn.commit()
    conn.close()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X