Python >> Tutoriel Python >  >> Python

Comment vérifier si une liste Python est vide ?

Croyez-le ou non, la façon dont vous répondez à cette question dans votre code quotidien révèle votre véritable niveau de compétence Python à chaque maître codeur qui lit votre code.

Les codeurs débutants vérifient si une liste a est vide en utilisant des instructions brutes comme len(a)==0 ou a==[] . Bien que ceux-ci résolvent le problème - ils vérifient si une liste est vide - ils ne sont pas ce que ferait un codeur maître. Au lieu de cela, la façon la plus Pythonique de vérifier si une liste (ou tout autre itérable d'ailleurs) est vide est l'expression not a .

Vous pouvez l'appeler booléenne implicite (ou, plus formel, flexibilité de type ) :chaque objet en Python peut être implicitement converti en une valeur de vérité.

Voici un exemple dans notre shell Python interactif :essayez-le vous-même !

Exercice :Quelle est la sortie du code si vous ajoutez un élément à la liste a ?

Test de valeur de vérité et flexibilité de type

Python associe implicitement tout objet à une valeur booléenne. Voici quelques exemples :

  • Les entiers 1, 2 et 3 sont associés au booléen True .
  • L'entier 0 est associé au booléen False .
  • Les chaînes 'hello' , '42' , et '0' sont associés au booléen True .
  • La chaîne vide '' est associé au booléen False .

En gros, chaque fois qu'une valeur booléenne est attendue, vous pouvez ajouter un objet Python à la place. L'objet Python sera ensuite converti en une valeur booléenne. Cette valeur booléenne sera utilisée pour décider d'entrer, disons, un while boucle ou un if déclaration. C'est ce qu'on appelle la "flexibilité de type" et c'est l'un des principaux choix de conception de Python.

Par défaut, tous les objets sont considérés True s'ils sont sémantiquement non vides. Les objets vides sont généralement associés au booléen False . Plus précisément, seulement si l'un des deux cas est rempli, le résultat d'un objet sera False :(i) le __len__() la fonction renvoie 0, ou (ii) le __bool__() la fonction renvoie False . Vous pouvez redéfinir ces deux méthodes pour chaque objet.

À partir de la documentation Python, voici quelques objets communs associés au booléen False :

  • Constantes définies :None et False .
  • Zéro de types numériques :0 , 0.0 , 0j , Decimal(0) , Fraction(0, 1)
  • Itérables vides :'' , () , [] , {} , set() , range(0)

Voici quelques exemples :

if []: print('1')

if (): print('2')

if [()]: print('3')
# 3

if 0: print('4')

if 0.00: print('5')

if 0.001: print('6')
# 6

if set(): print('7')

if [set()]: print('8')
# 8

Encore une fois, même si l'itérable ne contient qu'un seul élément (qui peut être évalué à False comme l'entier 0 ), la conversion booléenne implicite renverra True car un élément vide est néanmoins un élément.

Recommandation PEP8 :Comment vérifier si une liste est vide

Comme certains lecteurs se sont disputés avec moi sur la façon de vérifier correctement une liste vide en Python, voici l'extrait explicite de la norme PEP8 (ensemble de règles de Python sur la façon d'écrire du code lisible) :

Pour les séquences (chaînes, listes, tuples), utilisez le fait que les séquences vides sont fausses :

# Correct:
if not seq:
if seq:
# Wrong:
if len(seq):
if not len(seq):

Évaluations des performances

Pour voir laquelle des trois méthodes est la plus rapide, j'ai répété chaque méthode 100 fois en utilisant le timeit bibliothèque sur mon ordinateur portable avec un processeur Intel Core i7 (TM) de 8e génération, 8 Go de RAM - oui, je sais - et une carte graphique NVIDIA (peu importe).

Voici le code :

import timeit
import numpy as np

setup = 'a = []'

method1 = 'if len(a) == 0: pass'
method2 = 'if a == []: pass'
method3 = 'if not a: pass'

t1 = timeit.repeat(stmt=method1, setup=setup, repeat=100)
t2 = timeit.repeat(stmt=method2, setup=setup, repeat=100)
t3 = timeit.repeat(stmt=method3, setup=setup, repeat=100)


print('Method 1: len(a) == 0')
print('avg: ' + str(np.average(t1)))
print('var: ' + str(np.var(t1)))
print()

print('Method 2: a == []')
print('avg: ' + str(np.average(t2)))
print('var: ' + str(np.var(t2)))
print()

print('Method 3: not a')
print('avg: ' + str(np.average(t3)))
print('var: ' + str(np.var(t3)))
print()

La troisième méthode est la plus Pythonique avec une flexibilité de type. Nous mesurons le temps écoulé de 100 exécutions de chaque méthode. En particulier, nous nous intéressons au temps moyen et à la variance du temps écoulé. Les deux doivent être minimes.

Notre thèse est que la troisième méthode, la plus pythonique, est également la plus rapide car il n'est pas nécessaire de créer une nouvelle liste vide (comme dans la méthode 2) ou d'effectuer des appels de fonction imbriqués comme dans la méthode 1. La méthode 3 ne consiste qu'en un seul appel de fonction :convertir la liste en une valeur booléenne avec le __bool__ ou __len__ méthodes.

Voici le résultat en termes de durée d'exécution moyenne écoulée et de variance des durées d'exécution :

Method 1: len(a) == 0
avg: 0.06273576400000003
var: 0.00022597495215430347

Method 2: a == []
avg: 0.034635367999999944
var: 8.290137682917488e-05

Method 3: not a
avg: 0.017685209000000004
var: 6.900910317342067e-05

Vous pouvez voir que la troisième méthode est non seulement 50 % plus rapide que la méthode 2 et 75 % plus rapide que la méthode 3, mais qu'elle présente également très peu de variance. C'est clairement la meilleure méthode en termes de performances d'exécution. Étant également la méthode la plus courte, vous pouvez maintenant voir pourquoi la méthode est considérée comme la plus "Pythonic".