Skip to content

Opérateur in en Python (pour liste, chaîne, dictionnaire, etc.)

En Python, les opérateurs in et not in testent l’appartenance à des listes, des tuples, des dictionnaires, etc.

Cet article décrit le contenu suivant.

  • Comment utiliser l’opérateur in
    • Utilisation de base
    • Testé pour savoir s’ils sont égaux en valeur
    • Avec l’instruction if
    • dans le dictionnaire (dict)
    • in pour la chaîne (str)
  • pas dans (négation de dans)
  • in pour plusieurs éléments
  • Complexité temporelle de in
    • Lent pour la liste :O(n)
    • Rapide pour l’ensemble :O(1)
    • Pour le dictionnaire
  • in in pour les déclarations et la liste des compréhensions

Le mot in est également utilisé dans pour les déclarations et les compréhensions de liste. Voir les articles suivants pour plus de détails.

Comment utiliser l’opérateur in

Utilisation de base

x dans y renvoie True si x est inclus dans y et False si ce n’est pas le cas.

print(1 in [0, 1, 2])
# True

print(100 in [0, 1, 2])
# False

Non seulement la liste, mais aussi le tuple, l’ensemble, la plage et d’autres objets itérables peuvent être utilisés.

print(1 in (0, 1, 2))
# True

print(1 in {0, 1, 2})
# True

print(1 in range(3))
# True

Le dictionnaire (dict) et la chaîne (str) sont décrits plus loin.

Testé pour savoir s’ils sont égaux en valeur

Test by in est basé sur le fait que les valeurs sont égales ou non ainsi que ==. Il vaut True si la valeur est égale même si le type est différent.

print(1.0 == 1)
# True

print(1.0 in [0, 1, 2])
# True

print(True == 1)
# True

print(True in [0, 1, 2])
# True

Notez que bool est une sous-classe de entier int, donc True et False sont respectivement équivalents à 1 et 0.

Avec l’instruction if

in renvoie une valeur booléenne (True, False) et peut être utilisée directement dans l’instruction if.

l = [0, 1, 2]
i = 0

if i in l:
    print(f'{i} is a member of {l}.')
else:
    print(f'{i} is not a member of {l}.')
# 0 is a member of [0, 1, 2].
l = [0, 1, 2]
i = 100

if i in l:
    print(f'{i} is a member of {l}.')
else:
    print(f'{i} is not a member of {l}.')
# 100 is not a member of [0, 1, 2].

Notez que les listes, les tuples, les chaînes, etc. sont évalués comme False s’ils sont vides et True s’ils ne le sont pas. Si vous souhaitez vérifier si un objet est vide ou non, vous pouvez utiliser l’objet tel quel.

l = [0, 1, 2]

if l:
    print(f'{l} is not empty.')
else:
    print(f'{l} is empty.')
# [0, 1, 2] is not empty.
l = []

if l:
    print(f'{l} is not empty.')
else:
    print(f'{l} is empty.')
# [] is empty.

Voir également les articles suivants pour les tests de valeur de vérité pour chaque type.

dans le dictionnaire (dict)

Le fonctionnement du dictionnaire (dict) teste la clé.

d = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}

print('key1' in d)
# True

print('value1' in d)
# False

Utilisez values(), items() si vous voulez tester sur des valeurs ou des paires clé-valeur.

print('value1' in d.values())
# True

print(('key1', 'value1') in d.items())
# True

print(('key1', 'value2') in d.items())
# False

Voir l’article suivant pour plus de détails.

in pour la chaîne (str)

L’opération in pour la chaîne (str) teste l’existence d’une sous-chaîne.

print('a' in 'abc')
# True

print('x' in 'abc')
# False

print('ab' in 'abc')
# True

print('ac' in 'abc')
# False

pas dans (négation de dans)

x pas dans y renvoie la négation de x dans y.

print(10 in [1, 2, 3])
# False

print(10 not in [1, 2, 3])
# True

Le même résultat est renvoyé en ajoutant not à l’entier en opération.

print(not 10 in [1, 2, 3])
# True

Cependant, si vous ajoutez not à l’entier in operation, il sera interprété de deux manières, comme indiqué ci-dessous, il est donc recommandé d’utiliser le not in plus explicite.

print(not (10 in [1, 2, 3]))
# True

print((not 10) in [1, 2, 3])
# False

Étant donné que in a une priorité plus élevée que non, il est traité comme le premier s’il n’y a pas de parenthèses.

Ce dernier cas est reconnu comme suit.

print(not 10)
# False

print(False in [1, 2, 3])
# False

in pour plusieurs éléments

Si vous souhaitez vérifier si plusieurs éléments sont inclus, l’utilisation d’une liste de ces éléments comme suit ne fonctionnera pas. Il sera testé si la liste elle-même est incluse ou non.

print([0, 1] in [0, 1, 2])
# False

print([0, 1] in [[0, 1], [1, 0]])
# True

Utilisez et, ou ou ensembles.

Utilisez et, ou

Combinez plusieurs opérations en utilisant et et ou. Il sera testé si les deux ou l’un ou l’autre est inclus.

l = [0, 1, 2]
v1 = 0
v2 = 100

print(v1 in l and v2 in l)
# False

print(v1 in l or v2 in l)
# True

print((v1 in l) or (v2 in l))
# True

Étant donné que in et not in ont une priorité plus élevée que and et or, les parenthèses sont inutiles. Bien sûr, s’il est difficile à lire, vous pouvez le mettre entre parenthèses comme dans le dernier exemple.

Utiliser l’ensemble

Si vous avez beaucoup d’éléments à vérifier, il est plus facile d’utiliser l’ensemble que et, ou.

Par exemple, le fait que la liste A contienne tous les éléments de la liste B équivaut à savoir si la liste B est un sous-ensemble de la liste A.

l1 = [0, 1, 2, 3, 4]
l2 = [0, 1, 2]
l3 = [0, 1, 5]
l4 = [5, 6, 7]

print(set(l2) <= set(l1))
# True

print(set(l3) <= set(l1))
# False

Que la liste A ne contienne pas les éléments de la liste B équivaut à savoir si la liste A et la liste B sont relativement premières.

print(set(l1).isdisjoint(set(l4)))
# True

Si la liste A et la liste B ne sont pas relativement premières, cela signifie que la liste A contient au moins un élément de la liste B.

print(not set(l1).isdisjoint(set(l3)))
# True

Complexité temporelle de in

La vitesse d’exécution de l’opérateur in dépend du type de l’objet cible.

Les résultats de la mesure du temps d’exécution de in pour les listes, les ensembles et les dictionnaires sont présentés ci-dessous.

Notez que le code ci-dessous utilise la commande magique Jupyter Notebook %%timeit et ne fonctionne pas lorsqu’il est exécuté en tant que script Python.

Voir l’article suivant pour la complexité temporelle.

Prenons une liste de 10 éléments et 10000 éléments comme exemple.

n_small = 10
n_large = 10000

l_small = list(range(n_small))
l_large = list(range(n_large))

L’exemple de code ci-dessous est exécuté dans CPython 3.7.4, et bien sûr, les résultats peuvent varier en fonction de l’environnement.

Lent pour la liste : O(n)

La complexité temporelle moyenne de l’opérateur in pour les listes est O(n). Il devient plus lent lorsqu’il y a beaucoup d’éléments.

%%timeit
-1 in l_small
# 178 ns ± 4.78 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit
-1 in l_large
# 128 µs ± 11.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Le temps d’exécution varie fortement en fonction de la position de la valeur à rechercher. Il prend le plus de temps lorsque sa valeur est à la fin ou n’existe pas.

%%timeit
0 in l_large
# 33.4 ns ± 0.397 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%%timeit
5000 in l_large
# 66.1 µs ± 4.38 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%%timeit
9999 in l_large
# 127 µs ± 2.17 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Rapide pour l’ensemble : O(1)

La complexité temporelle moyenne de l’opérateur in pour les ensembles est O (1). Cela ne dépend pas du nombre d’éléments.

s_small = set(l_small)
s_large = set(l_large)

%%timeit
-1 in s_small
# 40.4 ns ± 0.572 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%%timeit
-1 in s_large
# 39.4 ns ± 1.1 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

Le temps d’exécution ne change pas en fonction de la valeur à rechercher.

%%timeit
0 in s_large
# 39.7 ns ± 1.27 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%%timeit
5000 in s_large
# 53.1 ns ± 0.974 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%%timeit
9999 in s_large
# 52.4 ns ± 0.403 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

Si vous souhaitez répéter l’opération pour une liste comportant de nombreux éléments, il est plus rapide de la convertir en ensemble à l’avance.

%%timeit
for i in range(n_large):
    i in l_large
# 643 ms ± 29.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
s_large_ = set(l_large)
for i in range(n_large):
    i in s_large_
# 746 µs ± 6.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Notez qu’il faut du temps pour convertir une liste en un ensemble, il peut donc être plus rapide de la conserver en tant que liste si le nombre d’opérations est petit.

Pour le dictionnaire

Prenons le dictionnaire suivant comme exemple.

d = dict(zip(l_large, l_large))
print(len(d))
# 10000

print(d[0])
# 0

print(d[9999])
# 9999

Comme mentionné ci-dessus, le fonctionnement du dictionnaire teste les clés.

La clé du dictionnaire est une valeur unique ainsi que l’ensemble, et le temps d’exécution est à peu près le même que pour les ensembles.

%%timeit
for i in range(n_large):
    i in d
# 756 µs ± 24.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

D’autre part, les valeurs du dictionnaire peuvent être dupliquées comme une liste. Le temps d’exécution de in for values() est à peu près le même que pour les listes.

dv = d.values()

%%timeit
for i in range(n_large):
    i in dv
# 990 ms ± 28.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Les paires clé-valeur sont uniques. Le temps d’exécution de in for items() est d’environ set + α.

di = d.items()

%%timeit
for i in range(n_large):
    (i, i) in di
# 1.18 ms ± 26.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

in in pour les déclarations et la liste des compréhensions

Le mot in est également utilisé dans pour les déclarations et les compréhensions de liste.

l = [0, 1, 2]

for i in l:
    print(i)
# 0
# 1
# 2
print([i * 10 for i in l])
# [0, 10, 20]

Voir les articles suivants pour plus de détails sur les déclarations et les compréhensions de liste.

Notez que l’opérateur in peut être utilisé comme condition dans les compréhensions de liste, ce qui prête à confusion.

l = ['oneXXXaaa', 'twoXXXbbb', 'three999aaa', '000111222']

l_in = [s for s in l if 'XXX' in s]
print(l_in)
# ['oneXXXaaa', 'twoXXXbbb']

Le premier in est in pour les compréhensions de liste, et le second in est l’opérateur in.