if-else Python : voici comment comprendre et utiliser l’instruction

L’instruction if-else en Python (en français : « si-(alors)-sinon ») est un branchement conditionnel et donc une structure de contrôle de base. L’utilisation d’un branchement conditionnel permet de suivre des chemins de code différents en fonction d’une condition rencontrée à l’exécution. Nous expliquons comment if-else fonctionne et est utilisé dans Python.

Certificats SSL IONOS

Gagnez la confiance de vos visiteurs en protégeant votre site Web avec un certificat SSL !

Activation facile
Sécurité maximale
Assistance 24/7

Qu’est-ce qu’une instruction if-else ?

L’instruction if-else est un branchement conditionnel. On peut se l’imaginer comme un aiguillage : en présence d’un élément de commutation, un seul des deux chemins possibles est emprunté. Python est un langage interprété ; l’interpréteur lit les lignes du code source de haut en bas. Dans le cas le plus simple, il en résulte un flux de programme strictement linéaire : toutes les lignes sont lues, interprétées et exécutées les unes après les autres.

En suivant ce schéma simple, il n’est toutefois pas possible de réaliser des programmes complexes. Ce n’est qu’en utilisant des structures de contrôle que l’on obtient la variabilité du code exécuté nécessaire dans la pratique. Un branchement permet l’exécution conditionnelle de certaines parties de code. Les autres structures de contrôle utilisées sont notamment les boucles Python for et les boucles Python while, qui permettent l’exécution répétée de parties de code.

Conseil

Apprenez à écrire du code Python grâce à notre tutoriel Python !

Comment fonctionne if-else en Python ?

En général, l’instruction if-else fonctionne en Python de la même manière que dans les autres langages. Il y a cependant quelques particularités spécifiques à Python. Voyons en détail comment fonctionne l’instruction if-else en Python et comment elle se comporte par rapport aux autres langages.

Syntaxe générale de l’instruction if-else en Python

La syntaxe générale de l’instruction if-else peut être exprimée directement en code Python. Nous définissons une condition et, dans le corps de l’instruction if, nous définissons par exemple un appel de fonction comme chemin de code à suivre lorsque la condition devient vraie. Nous définissons également dans le corps else un chemin de code à suivre dans le cas contraire :

if condition:
    if_body()
else:
    else_body()

La condition définie peut être soit vraie (True) soit fausse (False). Nous illustrons le modèle en inscrivant un littéral True ou False directement comme condition. Il en résulte un flux de programme statique dans lequel il est garanti qu’un seul des deux chemins est emprunté à la fois :

if False:
    # ce code ne sera jamais exécuté
    if_body()
else:
    else_body()
if True:
    if_body()
else:
    # ce code ne sera jamais exécuté
    else_body()

Bien entendu, ce modèle n’est pas pratique, il sert uniquement à illustrer. Au lieu d’une valeur True/False statique, une expression est utilisée comme condition. L’expression est évaluée lors de l’exécution du programme. On dit que l’expression est « évaluée ». Lors de l’évaluation de l’expression, une valeur de vérité est obtenue. Selon que la valeur de vérité est True ou False, le programme se branche dans l’une ou l’autre direction.

Il est important de comprendre que la partie else est facultative. Le code contenu dans le corps else n’est exécuté que si la condition ne s’applique pas. Cela n’est toutefois pas obligatoire. Souvent, une instruction if seule est suffisante :

if condition:
    if_body()

Une petite remarque sur la nomenclature : nous avons utilisé les termes « instruction » et « expression » sans les expliquer. Il est pourtant important de comprendre ce que l’on entend par là. Car ces deux notions fondamentales se retrouvent dans tous les langages de programmation. Voici un aperçu de la signification de ces termes :

Terme Nom anglais Explication
Instruction Statement Action qui est exécutée ; influence généralement le déroulement du programme
Expression Expression Terme qui renvoie une valeur lors de l’évaluation

Interroger plusieurs conditions exclusives avec l’instruction elif en Python

Outre la célèbre instruction if-else en Python, il existe une instruction elif apparentée. Une instruction if est suivie de plusieurs instructions elif optionnelles, suivies d’un bloc else optionnel. Une instruction elif n’est exécutée que si aucune des conditions précédentes n’est vraie. Cela garantit que seul un chemin de code unique défini est suivi :

if condition:
    if_body()
elif other_condition:
    elif_body()
elif another_condition:
    another_elif_body()
else:
    else_body()

Voici les règles de construction d’une branche if elif else enchaînée :

Instructions de branchement Nombre en combinaison
if exactement un
elif zéro ou plusieurs
else zéro ou un

Comment utiliser if-else en Python ?

L’instruction if-else est une fonctionnalité de base en Python et dans d’autres langages. Naturellement, il existe de nombreuses possibilités d’utilisation. Nous vous présentons des exemples courants, ainsi que les meilleures pratiques et les anti-patterns.

Utilisation correcte de la condition if en Python

Regardons d’abord comment fonctionne la condition d’une instruction de branchement. La condition est interprétée comme une expression booléenne qui évalue à l’une des valeurs de vérité True ou False. Il est donc inutile de tester explicitement l’égalité avec un littéral booléen :

if expression == True:
    ...

Même si la comparaison explicite avec True n’est pas une véritable erreur, le code ne fait pas professionnel. Les programmeurs expérimentés écrivent à la place :

if expression:
    ...

Examinons l’anti-pattern à l’aide d’un exemple. Supposons qu’une fonction is_odd() renvoie True pour un nombre si le nombre est impair. Dans le cas contraire, la fonction is_odd renvoie False. Nous utilisons la fonction dans une instruction if et affichons un texte correspondant :

if is_odd(number) == True:
   print("The number is odd.")

Imaginons ce qui se passe lors du passage du branchement avec un nombre impair. D’abord, l’expression 'is_odd(number) == True' évalue en 'True == True'. Cette dernière évalue à son tour en 'True' ; le corps if est exécuté. Il est plus judicieux d’utiliser directement la valeur booléenne renvoyée par la fonction is_odd comme condition :

if is_odd(number):
   print("The number is odd.")

Exécuter du code optionnel avec l’instruction if en Python

Imaginons la situation suivante : nous avons un bloc de code avec une certaine fonction. Les lignes sont exécutées les unes après les autres. Cependant, un élément du code ne doit pas être exécuté à chaque fois, mais uniquement lorsqu’une condition est remplie. Pour mettre en œuvre ce modèle, nous avons simplement besoin d’une instruction if. Illustrée ici par l’exemple d’une routine d’enregistrement d’utilisateur :

def register_user(user_data, do_newsletter_signup = False):
    # create user account
    user_account = create_account(user_data)
    # sign up for newsletter — only if requested by user
    if do_newsletter_signup:
        signup_newsletter(user_account)
    # send confirmation mail
    send_confirmation_mail(user_account)

Distinguer deux cas distincts avec l’instruction if-else en Python

Souvent, les programmes doivent distinguer deux cas qui s’excluent mutuellement. S’il est logiquement évident qu’il ne peut pas y avoir d’autres cas, il est judicieux d’utiliser une instruction if-else. A titre d’exemple, nous testons si une personne a atteint un certain âge et affichons à chaque fois un résultat approprié :

def is_of_age(person, age_limit = 18):
    if person.age >= age_limit:
        print("You're old enough")
    else:
        print("Sorry, wait some more")

Distinguer plusieurs cas exclusifs avec les instructions elif en Python

S’il y a plus de deux cas mutuellement exclusifs que nous voulons distinguer, nous utilisons des instructions elif enchaînées. Un else final sert à attraper la variante inconnue. Nous attribuons les noms de pays aux codes de pays correspondants :

def get_country_from_code(country_code):
    if country_code == 'DE':
        country = "Deutschland"
    elif country_code == 'ES':
        country = "España"
    elif country_code == 'FR':
        country = "France"
    elif country_code == 'GB':
        country = "Great Britain"
    elif country_code == 'IT':
        country = "Italia"
    else:
        country = None
    return country

Dans la mesure où la chaîne elif se trouve à l’intérieur d’une fonction, il est parfois préférable d’utiliser plusieurs instructions if indépendantes. Ainsi, nous évitons l’affectation dans le corps elif. L’instruction return permet de quitter la fonction si l’une des conditions est remplie. Au lieu du else final, on utilise une instruction return placée en dernier, qui n’est atteinte que si aucune des conditions n’est True :

def get_country_from_code(country_code):
    if country_code == 'DE':
        return "Deutschland"
    if country_code == 'ES':
        return "España"
    if country_code == 'FR':
        return "France"
    if country_code == 'GB':
        return "Great Britain"
    if country_code == 'IT':
        return "Italia"
    return None

Les instructions elif enchaînées sont un modèle bien connu des anciens langages. En Python, il est souvent plus direct d’utiliser un « Dictionary Lookup ». Nous définissons directement la correspondance entre les codes et les noms de pays et nous extrayons le nom à partir du code. Au lieu du else final, nous utilisons la méthode get intégrée, qui prend une valeur par défaut comme deuxième paramètre :

def get_country_from_code(country_code):
    countries = {
        'DE': "Deutschland",
        'ES': "España",
        'FR': "France",
        'GB': "Great Britain",
        'IT': "Italia",
    }
    country = countries.get(country_code, None)
    return country

Vérifier si un objet contient des données avec l’instruction if en Python

Python est un langage à typage dynamique. Au lieu d’être liés à des variables, les types sont liés à des valeurs. Selon l’utilisation, des conversions implicites entre types peuvent avoir lieu. Dans le contexte des expressions booléennes, on parle également de « truthy » et de « falsy » par extension des valeurs de vérité True et False.

Cela signifie que la condition d’une instruction if en Python n’a pas besoin d’être explicitement évaluée en True ou False. Au contraire, des valeurs d’autres types peuvent être utilisées comme condition. Celles-ci sont interprétées comme des valeurs booléennes selon certaines règles.

Citation

„Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations […]

[...] An object is considered true unless its class defines either a __bool__() method that returns False or a __len__() method that returns zero [...]“ – Source : https://docs.python.org/3/library/stdtypes.html#truth-value-testing

Traduction : « Tout objet peut être comparé à une valeur booléenne, typiquement dans une condition if ou while ou comme opérande des opérations booléennes [...]

[...] tout objet est considéré vrai à moins que sa classe définisse soit une méthode __bool__() renvoyant False soit une méthode __len__() renvoyant zéro [...] » (traduction de IONOS)

Nous utilisons ce modèle pour vérifier si un objet contient des données. Comme le texte suivant est vide, un message correspondant est affiché :

text = ''
if not text:
    print("No text given")

Les objets suivants sont évalués comme False dans un contexte booléen et sont donc appelés « falsy » :

Objet Explication
False, None Constantes qui, par définition, sont fausses
0, 0.0, Decimal(0), Fraction(0, 1), etc. Nombre représentant zéro
'', (), [], {}, set(), range(0), etc. Séquence ou collection vide

Un autre exemple avec une liste vide :

books_in_library = []
if not books_in_library:
    print("Library is empty")

Tous les autres objets sont évalués comme True :

number = 42
if number:
    print("Number exists")

Implémenter un interrupteur binaire avec if-else en Python

Une instruction if-else en Python est également utilisée pour passer d’un état à l’autre de manière exclusive. Le principe ressemble à un interrupteur de lumière et est appelé « toggle » en anglais. Nous définissons une fonction qui inverse l’état d’une lumière :

def toggle_light(light):
    if light == 'on':
        return 'off'
    else:
        return 'on'

Vous le voyez peut-être déjà : c’est encore plus simple. Si l’état n’est pas représenté par une chaîne de caractères, mais par une valeur booléenne, il est possible de renoncer complètement à l’instruction if. Au lieu de cela, nous utilisons l’opérateur logique NON pour inverser la valeur booléenne :

def toggle(boolean):
    return not boolean

Résoudre des instructions if imbriquées avec Early Return en Python

Dans la pratique, il est courant d’exécuter certains codes lorsque plusieurs conditions sont vraies en même temps. Pour les programmeurs inexpérimentés, cela conduit rapidement à des instructions if imbriquées. Il s’agit toutefois d’un mauvais style. En effet, il est difficile d’avoir une vue d’ensemble des ramifications profondément imbriquées et de les entretenir.

Prenons un exemple : nous écrivons une fonction qui indique si une personne peut voter. Nous vérifions d’abord si la personne possède une pièce d’identité. Ensuite, nous vérifions si la personne a déjà atteint l’âge de voter. Une première implémentation de la fonction contient des instructions if imbriquées :

def person_may_vote(person, voting_age = 18):
    if person.has_id():
        if person.get_age() >= voting_age:
            return True

Un problème immédiat de cette implémentation est que plus les conditions sont testées, plus le code le plus important est décalé. Pour résoudre les instructions if imbriquées, nous utilisons la meilleure pratique du « Early Return ». Nous vérifions au début de la fonction si les différentes conditions sont remplies. Si une condition n’est pas remplie, nous nous arrêtons et quittons la fonction en utilisant l’instruction return.

Nous reformulons notre fonction pour utiliser Early Return. Souvent, cela nécessite d’inverser les conditions définies précédemment. Pour cela, il est utile de comprendre les opérateurs booléens de Python. Si aucune des conditions négatives ne s’applique, le code pertinent est exécuté :

def person_may_vote(person, voting_age = 18):
    if not person.has_id():
        return False
    if person.age < voting_age:
        return False
    # if we made it here, the person may vote
    return True

Simplifier et remplacer les instructions if en Python à l’aide d’opérateurs logiques

Comme nous l’avons déjà vu, il est souvent nécessaire de tester la réalisation de plusieurs conditions. La plupart du temps, il n’est pas optimal d’utiliser des instructions if imbriquées pour tester plusieurs conditions. Prenons l’exemple d’un code qui détermine si une personne peut voter :

if has_id(person):
    if is_adult(person):
        print("You may vote")

La condition enchaînée peut être mieux représentée en utilisant des opérateurs logiques. Comme nous voulons tester si les deux conditions s’appliquent simultanément, nous utilisons l’opérateur logique ET. Ainsi, nous n’avons besoin que d’une seule instruction if :

if has_id(person) and is_adult(person):
    print("You may vote")

Voici un aperçu des opérateurs logiques de base en Python :

Opérateur logique Signification Syntaxe Python Autre langage    
ET L’expression est vraie si tous les opérandes sont vrais ; renvoie le dernier opérande évalué. and &&    
OU L’expression est vraie si au moins un des opérandes est vrai ; renvoie le dernier opérande évalué. or      
NON Inverse la valeur de l’expression. not !    

En plus de la liaison d’opérandes dans des conditions, les opérateurs logiques sont utilisés pour remplacer certaines instructions if. Il s’agit en l’occurrence de définir des valeurs par défaut.

Prenons un exemple : imaginons qu’un utilisateur puisse définir une devise pour un calcul financier. Pour des raisons de convivialité, ce choix doit être facultatif. Si l’utilisateur ne choisit pas de devise, EUR doit être utilisé comme valeur par défaut. Le code suivant illustre ce principe :

# user made no currency choice
currency = None
...
# further down in the program flow
if not currency:
    # set default if value missing
    currency = 'EUR'

En utilisant l’opérateur logique OU, l’instruction if peut être résolue. Nous réécrivons le code ; lorsqu’il est exécuté, la variable « currency » contient la valeur 'EUR' :

# user made no currency choice
currency = None
...
# further down in the program flow
# set default if value missing
currency = currency or 'EUR'

Que se passe-t-il ici exactement ? Dans la dernière ligne, une nouvelle valeur est attribuée à la variable 'currency'. Pour ce faire, l’expression 'currency or 'EUR' est d’abord évaluée à droite du signe égal. L’opérateur logique OU évalue d’abord l’expression de gauche, dans ce cas 'currency'. Comme celle-ci contient 'None' dans l’exemple et est donc 'falsy', l’expression de droite 'EUR' est évaluée et utilisée comme valeur de retour pour l’affectation.

L’opérateur conditionnel if-else en Python

En plus du branchement conditionnel, les mots clés if-else en Python ont une autre utilité. Il s’agit de l’opérateur conditionnel, également connu sous le nom d’opérateur « ternaire ». L’opérateur conditionnel est volontiers utilisé pour faire la distinction entre deux valeurs possibles dans les affectations.

Considérons d’abord un exemple utilisant l’instruction if-else en Python. Le code suivant définit Celsius ou Fahrenheit comme unité pour une mesure de température en fonction du système de mesure choisi :

if system == 'metric':
    unit = 'C'
else:
    unit = 'F'

En utilisant l’opérateur conditionnel, le code peut être simplifié en une seule instruction :

unit = 'C' if system == 'metric' else 'F'

Comme son nom l’indique, l’opérateur ternaire prend trois opérandes : les deux valeurs possibles et une expression comme condition.

Arité de l’opérateur Explication Exemple
Unaire L’opérateur accepte un opérande. not boolean_operand
Binaire L’opérateur accepte deux opérandes. left_operand + right_operand
Ternaire L’opérateur accepte trois opérandes. some_value if condition else other_value

Remplacer if-else dans Python avec l’instruction match-case

L’instruction match-case a été introduite avec la sortie de la version 3.10 de Python. Celle-ci rappelle l’instruction switch-case d’autres langages. Dans ce cas, switch-case est utilisé pour briser les grandes constructions if-elif-else.

Réputé pour être sujet aux erreurs, switch-case n’a jamais existé en Python. L’instruction match-case en Python est plutôt une fonctionnalité de « Structural Pattern Matching » inspirée des langages fonctionnels comme Haskell. Son utilité va bien au-delà de celle de switch-case.

Illustrons le principe de match-case par un exemple : imaginons que nous voulions traiter des données de personnes dans différents formats. Une personne peut être représentée soit sous la forme d’un nom unique, soit sous la forme d’un dictionnaire avec le nom et éventuellement l’âge, soit sous la forme d’un tuple de prénoms et de noms. Nous souhaitons également traiter le nom exact « Jack » de manière particulière :

# the name 'Jack'
person1 = 'Jack'
# just a name
person2 = 'John'
# name and age in a dict
person3 = {'name': 'Jim', 'age': 42}
# name in a dict, but no age
person4 = {'name': 'Walter', 'email': 'walter.white@example.com'}
# tuple of first and last name
person5 = ('Walther', 'White')

Regardons d’abord une fonction qui accueille une personne dans l’un des formats. Nous utilisons une chaîne if-elif-else et la fonction isinstance pour distinguer les différents formats. Nous utilisons également des conditions enchaînées avec l’opérateur ET et une instruction if-else imbriquée. Le code final n’est pas très explicite :

def greet_person(person):
    if isinstance(person, str):
        if person == 'Jack':
            print('Jack himself has arrived')
        else:
            print(f"Hi there, {person}")
    elif isinstance(person, dict) and 'name' in person and 'age' in person:
        print(f"It's, {person['name']}. Born {person['age']} years ago")
    elif isinstance(person, dict) and 'name' in person:
        print(f"It's {person['name']}")
    elif isinstance(person, tuple) and len(person) == 2:
        first, last = person
        print(f"Hello, {first} {last}")
    else:
        print('Not sure what kind of person this is')

Le code peut être construit plus joliment avec l’instruction match-case. Nous décrivons directement la structure des différents formats ; les valeurs individuelles peuvent être extraites en tant que variables. Le code est plus clair, moins complexe et plus lisible :

def match_person(person):
    match person:
        case 'Jack':
            print('Jack himself has arrived')
        case str() as name:
            print(f"Hi there, {name}")
        case {'name': name, 'age': age}:
            print(f"It's, {name}. Born {age} years ago")
        case {'name': name}:
            print(f"It's {name}")
        case (first, last):
            print(f"Hello, {first} {last}")
        case _:
            print('Not sure what kind of person this is')