Les fonctions Python

Apprends à écrire tes propres fonctions en Python. Définis et appelle des fonctions, transmets des valeurs à l’aide de paramètres, d’arguments nommés et de valeurs par défaut, puis renvoie des résultats avec return. Découvre les variables qu’une fonction peut voir et modifier, décris tes fonctions avec des docstrings et décompose un programme en petites fonctions aux noms explicites, que tu construis et testes une par une.

DébutantUnité 4 sur 10 de la formation Formation : Python : variables, boucles, fonctions et fichiers

Ce que tu vas apprendre

  1. Écris une fonction avec def, exécute-la en l’appelant et suis l’ordre dans lequel Python exécute un programme qui contient des fonctions.
    • Définir une fonction et l’appeler
      Écris l’en-tête et le corps indenté d’une fonction, choisis un nom explicite et exécute la fonction en l’appelant avec des parenthèses.
    • Suivre le flot d’exécution
      Suis l’ordre dans lequel Python exécute les instructions lorsque des fonctions en appellent d’autres, et prévois la sortie d’un programme à partir de cet ordre.
  2. Utilise des paramètres et des arguments pour fournir à une fonction les valeurs sur lesquelles elle travaille, en les associant par position, par nom ou au moyen de valeurs par défaut.
    • Utiliser des paramètres et des arguments positionnels
      Ajoute des paramètres à l’en-tête d’une fonction, transmets les arguments correspondants dans un appel et lis les erreurs produites par un nombre incorrect d’arguments.
    • Appeler des fonctions avec des arguments nommés
      Transmets des arguments par nom de paramètre, combine les arguments positionnels et nommés dans le bon ordre et corrige les erreurs dues à des combinaisons incorrectes.
    • Donner des valeurs par défaut aux paramètres
      Rends des paramètres facultatifs avec des valeurs par défaut, place correctement les paramètres obligatoires et facultatifs, et sache quand une valeur par défaut est créée.
  3. Utilise return pour renvoyer une valeur au code qui a appelé une fonction, distingue le renvoi de l’affichage et écris des fonctions dont les résultats peuvent être stockés, testés et combinés.
    • Renvoyer une valeur et l’utiliser
      Termine une fonction avec return, utilise la valeur renvoyée dans des variables et des expressions, et comprends pourquoi renvoyer une valeur est différent de l’afficher.
    • Renvoyer depuis différents chemins et combiner les résultats
      Écris des fonctions avec plusieurs instructions return, renvoie True ou False, effectue un retour anticipé depuis une boucle, renvoie deux valeurs et transmets le résultat d’une fonction à une autre.
  4. Prévois les variables qu’une fonction peut voir et modifier, fais entrer et sortir les données par des paramètres et des valeurs de retour, et utilise global seulement lorsque c’est vraiment nécessaire.
    • Manipuler des variables locales et des paramètres
      Explique pourquoi les variables créées dans une fonction n’existent que pendant son appel, comment Python trouve un nom et pourquoi modifier un paramètre ne modifie pas la variable de l’appelant.
    • Utiliser les variables globales avec prudence
      Lis les valeurs globales sans risque, comprends l’erreur causée par une affectation à un nom global, utilise correctement l’instruction global et privilégie les paramètres et les valeurs de retour.
  5. Décris des fonctions avec des docstrings, décompose un problème en petites fonctions aux noms explicites et construis et vérifie un programme fonction par fonction.
    • Documenter des fonctions avec des docstrings
      Écris des docstrings d’une ligne et multilignes qui suivent les conventions courantes, et lis-les avec help().
    • Décomposer un problème en fonctions
      Décompose une tâche en étapes, transforme chaque étape en fonction avec des entrées et des sorties explicites, et organise le programme autour d’une fonction main.
    • Construire et vérifier un programme fonction par fonction
      Développe un programme par petites étapes, teste chaque fonction avec des entrées dont tu connais les résultats et utilise les traces d’appels et des affichages temporaires pour trouver les bugs dans les fonctions.

Fonctions Python : cours

5 chapitres

1

Définir et appeler tes propres fonctions

Une fonction donne un nom à une partie utile du code, afin que tu puisses l’exécuter chaque fois que cette tâche est nécessaire. Écrire la définition et effectuer un appel sont deux actions distinctes, et cette différence explique pourquoi certains programmes se terminent sans rien afficher. Tu vas écrire des définitions correctement indentées, choisir des noms lisibles et suivre l’exécution lorsqu’une fonction en appelle une autre, puis revient à son appelant.

1.1 Définir une fonction et l’appeler

Une fonction est un bloc de code nommé qui accomplit une tâche. Les fonctions natives comme print() et input() te fournissent déjà des tâches utiles à appeler ; def te permet de créer les tiennes. Un bon nom transforme plusieurs lignes de travail en un appel qui indique ce que tu veux faire.

Écrire l’en-tête et le corps
def greet():
    print("Hello!")
    print("Welcome to Python.")

greet()
greet()

L’en-tête commence par def, puis viennent le nom, les parenthèses et les deux-points. Les lignes indentées forment le corps. Utilise quatre espaces pour chaque niveau d’indentation. Les lignes greet() non indentées sont hors de la fonction : ce sont donc des appels dans le programme principal.

Lorsque Python atteint la définition, il crée la fonction et lui donne le nom greet. Il n’affiche encore aucun des deux messages. Le premier appel commence à la première ligne du corps et affiche « Hello! » suivi de « Welcome to Python. ». Le second appel reprend le corps et affiche les deux mêmes lignes. Il y a quatre lignes de sortie en tout.

Un nom et un appel sont différents

Les parenthèses dans greet() en font un appel, même si cette fonction n’a besoin d’aucune entrée. Une ligne contenant seulement greet désigne la fonction et n’exécute rien. print(greet) affiche une description de l’objet fonction, avec une adresse mémoire ; il n’exécute pas le message de bienvenue.

Python doit avoir exécuté une définition avant qu’un appel utilise son nom. Si un fichier commence par greet() et définit greet ensuite, la première ligne déclenche NameError: name 'greet' is not defined. Place la définition avant l’appel au premier niveau du fichier.

Choisir des noms qui expliquent la tâche

Utilise des mots en minuscules reliés par des traits de soulignement, comme print_receipt ou convert_to_miles. Les noms peuvent contenir des lettres, des chiffres et des traits de soulignement, mais ne peuvent pas commencer par un chiffre ni être un mot réservé comme return. Les noms sont sensibles à la casse : greet et Greet sont des noms différents.

Garde les noms natifs disponibles. Après input = "yes", le nom input désigne du texte : input("Name? ") déclenche donc TypeError: 'str' object is not callable. Nommer la variable answer permet de garder la fonction native accessible.

Corriger d’abord la structure

L’absence des deux-points dans l’en-tête produit SyntaxError: expected ':'. Un corps vide ou non indenté produit une IndentationError. Une fonction en cours de conception a tout de même besoin d’une instruction ; pass est une instruction provisoire qui ne fait rien :

def print_receipt():
    pass

print_receipt()

Ce programme s’exécute sans rien afficher. L’appel atteint pass puis la fin du corps. Remplace l’instruction provisoire par la tâche réelle lorsque tu es prêt à l’implémenter. Si une ligne devait appartenir au corps mais s’exécute au mauvais moment, vérifie son indentation avant de modifier l’appel.

Points clés

  • Utilise def name(): et un corps indenté pour définir une fonction.
  • Une définition crée la fonction ; les parenthèses constituent un appel qui l’exécute.
  • Exécute la définition d’une fonction avant d’effectuer un appel qui a besoin de son nom.
  • Choisis des noms descriptifs en minuscules avec des traits de soulignement et évite les noms natifs.
  • Utilise pass lorsqu’une fonction en cours de conception a besoin d’un corps provisoire valide.

1.2 Suivre le flot d’exécution

Un programme avec des fonctions n’exécute pas chaque corps dans l’ordre où il apparaît sur la page. Un appel modifie le flot d’exécution : Python entre dans la fonction appelée, termine son travail, puis reprend l’exécution dans l’appelant juste après cet appel.

Suivre un appel dans un autre appel
def line():
    print("----------")

def banner():
    line()
    print("  REPORT")
    line()

print("Start")
banner()
print("End")

Python définit d’abord line et banner. Aucun des deux corps ne s’exécute. L’instruction suivante affiche « Start ». L’appel à banner() entre dans son corps, dont la première instruction appelle line().

Python entre alors dans line, affiche « ---------- » et atteint sa fin. Il revient à l’instruction suivante dans banner, qui affiche « REPORT ». Le second appel à line() affiche une autre ligne de tirets. Enfin, banner se termine : le programme principal reprend et affiche « End ».

La sortie est :

Start
----------
  REPORT
----------
End
Suivre les appels non terminés

Pendant que line s’exécute, banner attend qu’elle se termine. Le programme principal attend lui aussi banner. Python enregistre ces appels non terminés dans la pile d’appels. L’appel actif le plus interne se termine en premier, et chaque appelant reprend à son instruction suivante.

Pour suivre l’exécution sur papier, numérote les lignes du programme. Ne note une ligne du corps que lorsque l’exécution l’atteint par un appel. À chaque appel, indique où reprendre. Écris la sortie lorsque son print s’exécute, en conservant les espaces et les sauts de ligne. Cela distingue le parcours dans le code de la sortie produite.

Définir les fonctions auxiliaires avant qu’elles soient nécessaires

La définition d’une fonction auxiliaire peut apparaître sous celle de l’appelant :

def show_report():
    draw_line()
    print("Ready")

def draw_line():
    print("====")

show_report()

Cela fonctionne parce que les deux définitions ont été exécutées avant que l’appel final entre dans show_report. Python cherche draw_line lorsque le corps l’appelle effectivement. Déplacer show_report() au-dessus de def draw_line(): ferait échouer l’appel lorsqu’il essaierait d’utiliser la fonction auxiliaire manquante.

Les appels répétés repartent du début

Un appel dans une boucle entre dans le corps à chaque répétition :

for i in range(3):
    line()

Avec la première définition de line, cela affiche la ligne de tirets trois fois. La fonction commence à la première instruction de son corps à chaque appel.

Si un appel échoue, Python affiche une trace d’appels. Sa dernière ligne donne le type et le message de l’erreur. Les entrées d’appel qui la précèdent vont de l’appel non terminé le plus externe jusqu’à la ligne qui a échoué. Lire d’abord la dernière erreur, puis vérifier la ligne la plus interne et son appelant, aide à repérer l’opération qui a échoué et le chemin par lequel ses données lui sont parvenues.

Points clés

  • Suis les instructions des corps dans l’ordre des appels, en notant la sortie lorsque chaque print s’exécute.
  • La pile d’appels garde la trace des appels non terminés et de l’endroit où reprendre.
  • Une fonction auxiliaire peut être définie sous son appelant si sa définition s’exécute avant son appel.
  • Lis la dernière erreur d’une trace d’appels, puis examine la ligne qui a échoué et son appelant.
2

Transmettre des informations aux fonctions

Les paramètres permettent à une fonction de traiter différentes entrées sans réécrire son corps. L’appelant fournit des arguments et Python associe ces valeurs aux noms des paramètres avant que le corps commence. Tu vas associer les arguments par position et par nom, combiner correctement ces formes et choisir des valeurs par défaut pour les cas courants. Tu verras aussi pourquoi une valeur par défaut est créée lors de l’exécution de la définition et comment cela affecte une liste utilisée comme valeur par défaut.

2.1 Utiliser des paramètres et des arguments positionnels

Une fonction devient réutilisable avec différentes entrées lorsque son en-tête nomme les valeurs dont elle a besoin. Ces noms sont des paramètres. L’appelant fournit des arguments, qui sont les valeurs effectivement utilisées pour un appel donné.

Associer les valeurs aux noms
def rectangle_area(width, height):
    print("Area:", width * height)

rectangle_area(4, 2.5)
rectangle_area(3, 7)

Les paramètres sont width et height. Dans le premier appel, les arguments sont 4 et 2.5. Les arguments positionnels sont associés de gauche à droite : width reçoit 4 et height reçoit 2,5. Le corps affiche « Area: 10.0 ». L’appel suivant donne de nouvelles valeurs aux mêmes noms de paramètres et affiche « Area: 21 ».

Chaque paramètre joue le rôle d’une variable pendant cet appel. Tu n’as pas besoin d’affecter des valeurs à width et height au préalable ; l’appel les fournit. Une fonction sans paramètres a quand même besoin de parenthèses vides dans sa définition et dans ses appels.

L’ordre peut changer le sens
def describe_pet(animal, name):
    print(name, "is a", animal)

describe_pet("cat", "Milo")
describe_pet("Milo", "cat")

Le premier appel affiche « Milo is a cat ». Le second affiche « cat is a Milo ». Les deux appels sont valides en Python : aucune erreur ne signale donc l’inversion du sens. Lis l’ordre de l’en-tête avant de choisir les arguments positionnels, surtout lorsque plusieurs paramètres acceptent le même type de valeur.

Les arguments peuvent être des expressions

Python évalue chaque expression utilisée comme argument avant que le corps commence. Avec side = 6, l’appel rectangle_area(side, side) transmet deux fois 6 et affiche « Area: 36 ». Le nom de la variable de l’appelant n’a besoin de correspondre à aucun des deux noms de paramètres. L’appel rectangle_area(side + 1, 2) transmet 7 et 2 ; il ne transmet pas le texte « side + 1 ».

Lire une erreur de nombre d’arguments

Chaque paramètre sans valeur par défaut a besoin d’un argument. Avec la fonction d’aire ci-dessus :

AppelProblème
rectangle_area(4)height manque.
rectangle_area(4, 2, 1)Trois arguments ont été fournis pour deux paramètres.

Le premier déclenche TypeError: rectangle_area() missing 1 required positional argument: 'height'. Le second déclenche TypeError: rectangle_area() takes 2 positional arguments but 3 were given. Vérifie l’en-tête de la fonction indiquée, puis compte comment l’appel renseigne ses paramètres.

Transmettre le type de valeur nécessaire à la tâche

Python n’impose pas un type simplement parce qu’un paramètre s’appelle width. rectangle_area("4", 2) affiche « Area: 44 », car multiplier du texte par un entier répète ce texte. Comme input() renvoie du texte, convertis une saisie numérique avant de la transmettre :

width = float(input("Width: "))
rectangle_area(width, 2)

Ici, float() transforme le texte saisi en nombre avant que la fonction d’aire le reçoive.

Points clés

  • Un paramètre est un nom dans l’en-tête ; un argument est une valeur fournie par un appel.
  • Les arguments positionnels renseignent les paramètres de gauche à droite.
  • Python évalue les expressions des arguments avant l’exécution du corps de la fonction.
  • Chaque paramètre obligatoire a besoin d’une valeur ; des arguments manquants ou en trop déclenchent une TypeError.
  • Convertis une saisie numérique reçue sous forme de texte avant de la transmettre à un calcul.

2.2 Appeler des fonctions avec des arguments nommés

Un argument nommé indique dans l’appel le paramètre auquel il est destiné. Cela rend l’appel plus facile à lire lorsque plusieurs valeurs pourraient être confondues. Python associe le nom indiqué à celui de l’en-tête au lieu d’utiliser sa position.

Associer par nom
def describe_pet(animal, name):
    print(name, "is a", animal)

describe_pet(name="Milo", animal="cat")
describe_pet(animal="cat", name="Milo")

Les deux appels affichent « Milo is a cat ». L’ordre des arguments nommés peut changer, car chaque valeur indique le paramètre qu’elle renseigne. La même idée rend rectangle_area(width=4, height=2.5) lisible sans vérifier quelle dimension vient en premier.

Un nom indiqué dans un argument nommé n’est pas une nouvelle variable dans le code appelant. Dans describe_pet(name="Milo", animal="cat"), name= dirige « Milo » vers le paramètre. Il n’affecte pas « Milo » à une variable appelée name au premier niveau du fichier. Écris les arguments nommés sans espaces autour de =, conformément au style habituel de Python.

Combiner des arguments positionnels et nommés
describe_pet("cat", name="Milo")

Le premier argument renseigne animal par sa position. L’argument nommé renseigne name : chaque paramètre reçoit donc exactement une valeur. Les arguments positionnels doivent venir en premier. L’appel describe_pet(name="Milo", "cat") est rejeté avec SyntaxError: positional argument follows keyword argument.

Pour examiner un appel mixte, renseigne les emplacements positionnels de gauche à droite, puis associe les arguments nommés. Vérifie qu’aucun emplacement n’est renseigné deux fois et qu’aucun emplacement obligatoire ne reste vide.

Corriger les noms en double ou inconnus
AppelDiagnostic
describe_pet("cat", animal="dog")animal reçoit à la fois « cat » et « dog ».
describe_pet(animal="cat", nmae="Milo")L’en-tête n’a aucun paramètre appelé nmae.

Le doublon déclenche TypeError: describe_pet() got multiple values for argument 'animal'. La faute de frappe déclenche TypeError: describe_pet() got an unexpected keyword argument 'nmae'. Compare les noms caractère par caractère ; les majuscules et les minuscules comptent aussi. Changer l’ordre des arguments ne corrige pas une double affectation à un même paramètre.

Reconnaître les arguments nommés dans les fonctions natives
print("a", "b", "c", sep="-")
print("Loading", end="...")
print("done")

La première ligne affiche « a-b-c ». sep fournit le texte entre les valeurs affichées. Les deux appels suivants produisent « Loading...done » sur une seule ligne : end remplace le saut de ligne habituel après « Loading ».

Certaines fonctions natives acceptent aussi des arguments nommés ; par exemple, round(3.14159, ndigits=2) donne 3,14. Utilise les noms de paramètres documentés pour la fonction que tu appelles. Un mot descriptif que tu inventes n’est pas reconnu simplement parce qu’il semble convenir à la tâche.

Points clés

  • Les arguments nommés correspondent aux noms des paramètres : leur ordre peut donc varier.
  • Place les arguments positionnels avant les arguments nommés.
  • Renseigne chaque paramètre exactement une fois et orthographie chaque nom exactement.
  • Dans un appel, un nom dirige une valeur vers un paramètre ; il n’affecte pas de valeur à une variable de l’appelant.
  • Pour print, sep contrôle les séparateurs et end contrôle la fin de l’affichage.

2.3 Donner des valeurs par défaut aux paramètres

Une valeur par défaut permet à un appel d’omettre un argument lorsqu’un choix courant convient. Écris la valeur par défaut à côté de son paramètre dans l’en-tête. Fournir un argument remplace la valeur par défaut pour cet appel.

Rendre un paramètre facultatif
def greet(name, greeting="Hello"):
    print(greeting + ",", name + "!")

greet("Ana")
greet("Ana", "Welcome")
greet("Ana", greeting="Hi")

La sortie est « Hello, Ana! », « Welcome, Ana! » et « Hi, Ana! ». name est obligatoire car il n’a pas de valeur par défaut. greet() déclenche donc une TypeError, même si l’autre paramètre est facultatif.

Dans ces en-têtes, les paramètres obligatoires précèdent les paramètres avec valeurs par défaut. def greet(greeting="Hello", name): est invalide. Python signale une erreur de syntaxe parce qu’un paramètre sans valeur par défaut suit un paramètre qui en a une. Déplace name avant greeting pour qu’il reste obligatoire.

Modifier un choix facultatif
def order_coffee(size, shots=1, milk="none"):
    print(size, "coffee,", shots, "shot(s), milk:", milk)

order_coffee("large", milk="oat")

Cet appel affiche « large coffee, 1 shot(s), milk: oat ». L’argument nommé atteint milk, tandis que shots garde 1. Un appel positionnel order_coffee("medium", 2) modifie shots et laisse milk à « none ». L’association positionnelle ne saute pas un paramètre facultatif pour atteindre le suivant.

Les fonctions natives proposent aussi des valeurs par défaut : un print() ordinaire sépare les valeurs par une espace et termine par un saut de ligne. round(3.7) donne l’entier 4 ; round(3.14159, 2) demande deux décimales et donne 3,14.

Les valeurs par défaut sont créées lors de l’exécution de la définition
rate = 0.05

def price_with_tax(price, tax_rate=rate):
    return price * (1 + tax_rate)

rate = 0.08
print(price_with_tax(100))
print(price_with_tax(100, rate))

La valeur par défaut stocke la valeur 0,05 lorsque def s’exécute. Modifier rate ensuite ne change pas cette valeur par défaut stockée. Les appels affichent « 105.0 » et « 108.0 » : seul le second fournit explicitement le nouveau taux.

Éviter de partager une liste par accident

Une liste contient des éléments, et append ajoute un élément à cette même liste. Avec une liste comme valeur par défaut, les appels qui omettent l’argument la partagent tous :

def add_item(item, basket=[]):
    basket.append(item)
    print(basket)

add_item("apple")
add_item("pear")

Cela affiche ['apple'] puis ['apple', 'pear']. La liste par défaut a été créée une seule fois, et non une fois par appel. Pour créer une nouvelle liste chaque fois que l’argument est omis, utilise None comme signal :

def add_item(item, basket=None):
    if basket is None:
        basket = []
    basket.append(item)
    print(basket)

Ces deux appels affichent maintenant ['apple'] et ['pear']. Une liste fournie explicitement est toujours utilisée telle quelle. Décris les paramètres facultatifs et leurs valeurs par défaut dans la docstring afin que les appelants sachent quelles valeurs sont choisies en cas d’omission.

Points clés

  • Un argument facultatif omis utilise sa valeur par défaut ; un argument explicite la remplace.
  • Place les paramètres obligatoires avant les paramètres avec valeurs par défaut.
  • Utilise un argument nommé pour modifier une option ultérieure sans renseigner les emplacements facultatifs précédents.
  • Les expressions des valeurs par défaut sont évaluées une seule fois lorsque def s’exécute.
  • Une liste mutable utilisée comme valeur par défaut est partagée par les appels qui omettent l’argument.
  • Utilise None et crée une liste dans le corps lorsqu’il faut une nouvelle liste chaque fois que l’argument est omis.
3

Renvoyer des résultats avec des valeurs de retour

Un calcul devient plus utile lorsque son résultat peut alimenter un autre calcul, une condition ou un affichage. L’instruction return le permet en renvoyant une valeur à l’appelant. Tu vas distinguer le renvoi de l’affichage, suivre le premier return qui s’exécute et vérifier les chemins susceptibles de se terminer sans résultat utile. Tu construiras ensuite des fonctions booléennes, termineras correctement des recherches et combineras les résultats de petites fonctions.

3.1 Renvoyer une valeur et l’utiliser

Une fonction peut fournir à l’appelant un résultat à utiliser. L’instruction return termine l’appel et renvoie sa valeur. Au point d’appel, l’appel représente cette valeur renvoyée.

Stocker et combiner des résultats
def rectangle_area(width, height):
    return width * height

area = rectangle_area(4, 2.5)
print(area)
print(rectangle_area(3, 4) + rectangle_area(2, 5))

Le premier appel renvoie 10,0, qui est affecté à area ; le premier print l’affiche. Dans la dernière ligne, les deux appels renvoient 12 et 10. Python additionne ces résultats et affiche « 22 ». La fonction elle-même ne contient pas de print : elle peut donc fournir un résultat à stocker ou une partie d’un calcul plus large.

Une valeur renvoyée peut aussi être testée dans une condition ou transmise à une autre fonction. Cela distingue la tâche de calcul de la décision de l’appelant sur la façon d’utiliser la réponse.

Afficher et renvoyer ont des rôles différents
def double_print(n):
    print(n * 2)

result = double_print(5)
print(result)

L’appel affiche « 10 », mais ce nombre affiché n’est pas renvoyé comme résultat. double_print atteint la fin de son corps et renvoie donc None. La dernière ligne affiche par conséquent « None ».

OpérationDestination de la valeur
print(value)L’affiche pour une personne.
return valueLa transmet à l’appelant pour que le programme l’utilise.

double_print(5) + 1 affiche d’abord « 10 », puis déclenche TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'. Remplace le corps par return n * 2 lorsque l’appelant a besoin du nombre doublé. Une fonction destinée uniquement à produire un effet, comme afficher un message, peut tout à fait renvoyer None ; on appelle parfois ces fonctions des procédures. Une fonction qui renvoie un résultat utile est parfois appelée fonction avec valeur de retour.

S’arrêter au premier return exécuté
def to_fahrenheit(celsius):
    return celsius * 9 / 5 + 32
    print("Converted")

print(to_fahrenheit(20))

Cela affiche « 68.0 ». Le print dans le corps n’est jamais atteint, car return a déjà terminé l’appel. Supprime cette instruction inaccessible ou déplace une action nécessaire avant le return. La conversion renvoie des flottants car / produit un flottant. Les entrées 100 et -40 donnent 212,0 et -40,0.

Un return seul, sans expression, termine aussi un appel en renvoyant None. Chaque appel de fonction a un résultat, même lorsqu’aucune valeur utile n’a été fournie.

Rendre les résultats visibles dans un fichier programme

Dans un fichier, un rectangle_area(3, 4) placé seul calcule 12 puis abandonne le résultat inutilisé. Utilise print(rectangle_area(3, 4)) pour l’afficher ou affecte-le à une variable. La console interactive affiche les résultats des expressions sauf None : un essai réussi dans la console peut donc sembler différent de l’exécution de la même ligne dans un fichier.

Points clés

  • return value termine l’appel et fait que l’appel représente cette valeur.
  • Afficher montre une valeur ; renvoyer la rend disponible pour l’appelant.
  • Atteindre la fin du corps ou utiliser un return seul donne None.
  • Les instructions après un return exécuté ne s’exécutent pas pendant cet appel.
  • Utilise un résultat renvoyé en le stockant, en l’affichant, en le testant ou en le combinant.

3.2 Renvoyer depuis différents chemins et combiner les résultats

Des entrées différentes peuvent nécessiter des réponses différentes. Une fonction peut avoir plusieurs instructions return, mais un appel s’arrête à la première qu’il exécute. Suis le chemin réellement emprunté dans ses branches et ses boucles pour trouver le résultat.

Ordonner les tests qui se recoupent
def letter_grade(score):
    if score >= 90:
        return "A"
    if score >= 80:
        return "B"
    if score >= 70:
        return "C"
    return "F"

Pour 85, le premier test est faux et le deuxième est vrai. La fonction renvoie « B » sans tester les conditions restantes. Pour 42, les trois tests sont faux : le return final fournit donc « F ». Des instructions if distinctes fonctionnent parce que chaque branche dont le test est vrai termine l’appel.

Le seuil le plus élevé doit ici être vérifié en premier. Si score >= 70 venait en premier, un score de 95 renverrait « C ». Lorsque des intervalles se recoupent, une condition large placée tôt peut masquer une réponse ultérieure plus précise.

Couvrir le chemin sans branche correspondante
def sign(n):
    if n > 0:
        return "positive"
    elif n < 0:
        return "negative"
    return "zero"

La dernière ligne traite zéro. Sans elle, sign(0) atteindrait la fin et renverrait None. Suis une entrée pour chaque branche et pour tout cas restant ; tester seulement des entrées positives et négatives laisserait passer cet oubli.

Renvoyer une comparaison booléenne
def is_even(n):
    return n % 2 == 0

if is_even(10):
    print("Even")

La comparaison produit déjà True ou False. is_even(10) renvoie True, tandis que is_even(7) renvoie False. Utilise directement le résultat dans une condition. Un == True supplémentaire n’apporte rien au test.

Terminer une recherche avant de conclure à l’absence de correspondance
def smallest_divisor(n):
    for d in range(2, n):
        if n % d == 0:
            return d
    return n

Pour 91, les diviseurs possibles de 2 à 6 échouent, puis 7 le divise sans reste. Renvoyer 7 termine à la fois la boucle et la fonction. Pour 13, la boucle ne trouve aucun diviseur : le return final donne donc 13.

Un test de primalité doit permettre à la recherche de continuer après l’échec d’un diviseur possible :

def is_prime(n):
    if n < 2:
        return False
    for d in range(2, n):
        if n % d == 0:
            return False
    return True

Le True final est hors de la boucle. Le placer dans un else à l’intérieur de la boucle provoquerait un retour après la vérification du premier diviseur possible seulement : 9 serait accepté à tort parce qu’il n’est pas divisible par 2. Avec la fonction corrigée, 9 et 1 donnent False ; 2, 7 et 97 donnent True. Pour 2, la boucle n’a aucun diviseur à essayer et l’exécution atteint le True final.

Renvoyer deux valeurs
def share(total, people):
    return total // people, total % people

each, left = share(17, 5)
print(each, left)

L’appel renvoie un tuple, un résultat regroupé contenant 3 et 2. L’affectation le dépaquette en deux noms : la sortie est donc « 3 2 ». Afficher directement l’appel montrerait « (3, 2) ». Le nombre de noms doit correspondre au nombre de valeurs dépaquetées.

Combiner les appels de l’intérieur vers l’extérieur
def add(a, b):
    return a + b

def to_fahrenheit(celsius):
    return celsius * 9 / 5 + 32

print(to_fahrenheit(add(10, 15)))

add renvoie d’abord 25. Cette valeur devient l’argument de to_fahrenheit, qui renvoie 77,0. Enfin, print affiche « 77.0 ». Chaque appel interne doit renvoyer la valeur dont la fonction suivante a besoin.

Points clés

  • Le premier return exécuté termine un appel : ordonne donc soigneusement les tests qui se recoupent.
  • Prévois un résultat utile pour chaque chemin d’entrée que la fonction doit traiter.
  • Une fonction booléenne peut renvoyer directement une comparaison.
  • Dans une boucle de recherche, renvoie un résultat trouvé ; indique l’absence de correspondance après l’échec de tous les candidats.
  • Des valeurs renvoyées séparées par des virgules forment un tuple qui peut être dépaqueté.
  • Dans des appels imbriqués, le résultat de l’appel interne devient l’argument de l’appel externe.
4

Savoir où vivent les variables : portée locale et portée globale

Un nom dans une fonction peut sembler identique à un nom extérieur tout en désignant une variable distincte. La portée indique où un nom peut être utilisé, et l’affectation aide à déterminer quel nom Python désigne. Tu vas suivre les paramètres et les autres variables locales pendant un appel, distinguer la réaffectation de la modification d’une liste partagée et lire des paramètres globaux. Tu corrigeras aussi une erreur de portée courante et rendras explicites les valeurs qui changent dans les appels.

4.1 Manipuler des variables locales et des paramètres

La portée indique où un nom peut être utilisé. Les paramètres et les noms auxquels une valeur est affectée dans une fonction sont locaux à l’appel de cette fonction. Un appelant et une fonction peuvent utiliser des noms similaires sans partager les mêmes variables locales.

Garder les noms locaux dans leur appel
def make_greeting():
    message = "Hi"
    print(message)

make_greeting()

Cela affiche « Hi ». Ajouter print(message) après l’appel déclenche NameError: name 'message' is not defined : le nom local n’est pas disponible à cet endroit. Pour rendre la valeur disponible à l’appelant, renvoie-la et stocke-la :

def make_greeting():
    return "Hi"

message = make_greeting()
print(message)

Le message au premier niveau du fichier est une nouvelle variable de l’appelant qui reçoit la valeur renvoyée. La fonction ne rend pas ses propres noms locaux visibles à l’extérieur.

Chaque appel reçoit de nouvelles variables locales. Si un corps affecte count = 0, ajoute 1 et l’affiche, deux appels affichent « 1 » et « 1 ». Le second appel ne continue pas avec le compteur du premier. Différentes fonctions peuvent aussi utiliser indépendamment des noms locaux comme total.

Suivre le masquage et la recherche des noms
x = 10

def show():
    x = 5
    print(x)

show()
print(x)

La sortie est « 5 » puis « 10 ». La variable locale x masque la variable globale x dans show ; l’affectation ne modifie pas la valeur au premier niveau du fichier. Une variable globale appartient à la portée du premier niveau du fichier. Les affectations ordinaires hors des fonctions créent des variables globales.

Pour une fonction définie au premier niveau du fichier, Python cherche un nom parmi ses noms locaux, puis parmi les noms globaux du fichier, puis parmi les noms natifs comme print. La première correspondance l’emporte. Les noms locaux et globaux sont donc deux endroits différents à vérifier lorsqu’une valeur semble incorrecte.

Réaffecter un paramètre ne modifie pas la variable de l’appelant
def add_bonus(points):
    points = points + 10
    print(points)

score = 50
add_bonus(score)
print(score)

points commence avec la valeur 50. Sa réaffectation locale lui donne la valeur 60 : la première sortie est donc « 60 ». La variable score de l’appelant vaut toujours 50. Pour mettre explicitement ce nom à jour, utilise une fonction qui renvoie points + 10, puis écris score = add_bonus(score).

Modifier une liste est une opération différente

Une liste peut être partagée par deux noms :

def add_guest(guests, name):
    guests.append(name)

party = ["Ana"]
add_guest(party, "Ben")
print(party)

Le paramètre guests et la variable party de l’appelant désignent la même liste. append modifie le contenu de cette liste : la sortie est donc « ['Ana', 'Ben'] ». Affecter guests = [] dans la fonction ferait en revanche désigner une nouvelle liste au seul nom local ; party désignerait toujours la liste d’origine. Lorsque tu suis un argument de type liste, demande-toi si la ligne modifie l’objet partagé ou réaffecte seulement un nom local.

Points clés

  • Les paramètres et les noms auxquels une valeur est affectée dans une fonction sont locaux à son appel.
  • Chaque appel reçoit de nouvelles variables locales ; les valeurs de retour transmettent les résultats vers l’extérieur.
  • Un nom local peut masquer un nom global sans modifier la valeur globale.
  • Réaffecter un paramètre laisse la variable de l’appelant inchangée.
  • Modifier une liste partagée change la liste que voit l’appelant.

4.2 Utiliser les variables globales avec prudence

Une fonction peut lire un nom global sans déclaration. Affecter une valeur à un nom dans son corps suit une règle différente, et confondre ces opérations est une cause courante d’UnboundLocalError.

Lire un paramètre fixe
TAX_RATE = 0.25

def tax(amount):
    return amount * TAX_RATE

print(tax(80))

La sortie est « 20.0 ». amount est local ; TAX_RATE est lu parmi les noms globaux du fichier. Par convention, les majuscules marquent une constante et indiquent que le programme doit laisser ce paramètre fixe. Python n’impose pas cette convention.

Une affectation rend un nom local dans tout le corps
total = 0

def add_to_total(amount):
    total = total + amount

add_to_total(5)

L’affectation rend total local dans toute la fonction add_to_total. Pour calculer le membre de droite, Python essaie de lire ce nom local avant qu’il ait une valeur. Il ne se rabat pas sur le total global. L’appel déclenche UnboundLocalError: cannot access local variable 'total' where it is not associated with a value.

La décision repose sur tout le corps, pas seulement sur les lignes déjà exécutées. Un corps avec print(count) suivi de count = 10 considère aussi count comme local à la ligne d’affichage. Un count global ne peut pas fournir la valeur locale manquante.

Déclarer une affectation globale délibérée
total = 0

def add_to_total(amount):
    global total
    total = total + amount

add_to_total(5)
add_to_total(7)
print(total)

La lecture et l’affectation désignent maintenant toutes deux le nom global : la sortie est donc « 12 ». Place global total avant toute utilisation de total dans la fonction. Utiliser le nom avant sa déclaration est une erreur de syntaxe.

Une déclaration seule ne crée pas de valeur. Une affectation ultérieure peut créer une variable globale qui n’existait pas : le corps d’une fonction contenant global level puis level = 1 crée le level global lors de son appel.

Montrer le changement par les entrées et un résultat

Le même total cumulé peut être écrit avec une interface explicite :

def add_to_total(total, amount):
    return total + amount

total = 0
total = add_to_total(total, 5)
total = add_to_total(total, 7)
print(total)

Cela affiche aussi « 12 ». Chaque appel montre l’ancienne valeur transmise, et l’affectation montre où va la nouvelle valeur. Tu peux vérifier add_to_total(10, 3) indépendamment, sans initialiser d’abord un état global caché. Lorsque plusieurs fonctions modifient la même variable globale, leur comportement dépend de leur ordre d’exécution.

Opération dans une fonctionDéclaration nécessaire ?
Lire un paramètre globalNon.
Réaffecter un nom globalglobal name avant utilisation.
Ajouter un élément à une liste globale existanteNon ; le nom n’est pas réaffecté.

Lire une liste partagée et modifier son contenu utilise la référence existante. Faire désigner une autre liste à ce nom global est une affectation : la règle d’affectation s’applique donc.

Points clés

  • Lis un nom global sans déclaration particulière.
  • Une affectation n’importe où dans une fonction rend ce nom local, sauf s’il est déclaré global.
  • La lecture d’un nom local auquel aucune valeur n’a été affectée déclenche UnboundLocalError.
  • Place global name avant d’utiliser un nom que la fonction réaffecte volontairement au niveau global.
  • Privilégie les paramètres et les valeurs de retour lorsqu’une valeur changeante peut être transmise explicitement.
  • Modifier une liste et réaffecter son nom suivent des règles différentes.
5

Documenter et concevoir des programmes avec des fonctions

De bonnes fonctions ont besoin de tâches clairement définies ainsi que d’un code correct. L’appelant doit pouvoir voir ce dont une fonction a besoin, ce qu’elle renvoie et les effets qu’elle produit sans étudier chaque ligne de son corps. Tu vas écrire des docstrings, diviser un programme complet en fonctions auxiliaires et les relier au moyen d’une petite fonction main. Tu vérifieras ensuite chaque partie à l’aide de résultats attendus, d’entrées aux limites et des indices d’une trace d’appels.

5.1 Documenter des fonctions avec des docstrings

L’appelant doit connaître la tâche d’une fonction sans lire toute son implémentation. Une docstring fournit cette description. Python reconnaît une chaîne comme la docstring de la fonction lorsqu’elle est la première instruction du corps.

Écrire d’abord une courte description
def to_fahrenheit(celsius):
    """Convert a temperature from degrees Celsius to degrees Fahrenheit."""
    return celsius * 9 / 5 + 32

print(to_fahrenheit.__doc__)

La sortie est la phrase entre les guillemets. Python stocke la docstring dans __doc__ ; les triples guillemets ne font pas partie de la phrase stockée. help(to_fahrenheit) affiche la description avec la signature to_fahrenheit(celsius). Transmets le nom de la fonction à help, sans appeler la fonction.

La convention courante consiste à utiliser trois guillemets doubles, même pour une docstring d’une ligne. Commence par une instruction comme « Renvoyer l’aire d’un rectangle. » et termine par un point. Garde une courte description et ses guillemets de fermeture sur une seule ligne. Tu n’as pas besoin de répéter le nom de la fonction et la liste des paramètres, car l’aide les affiche déjà.

Ajouter des détails lorsque les appelants en ont besoin
def split_bill(total, people, tip_rate=0.2):
    """Return each person's share of a bill, including the tip.

    total: the bill before the tip
    people: the number of people sharing the bill
    tip_rate: the tip as a fraction of the bill (default 0.2)
    """
    return total * (1 + tip_rate) / people

La première ligne indique le résultat. Une ligne vide la sépare des détails sur les entrées. La valeur par défaut est documentée comme 0,2, une fraction de l’addition ; cela évite qu’un appelant prenne 20 pour la valeur voulue pour un pourboire de 20 %. Les guillemets de fermeture d’une docstring multiligne sont placés sur leur propre ligne.

Pour split_bill(84, 4), la fonction applique le pourboire par défaut et renvoie 25,2. L’appelant peut comprendre ce que signifient les trois entrées avant de choisir les arguments. Indique les unités lorsqu’elles comptent et décris les effets comme l’affichage, afin que l’appelant puisse prévoir le résultat et le comportement visible.

Distinguer la documentation des commentaires
FormeRôle principal
Première chaîne dans le corpsDécrit la fonction pour son appelant et apparaît dans help.
Commentaire # dans le corpsExplique un détail du code à la personne qui lit l’implémentation.

Une chaîne placée après une affectation ou une autre instruction du corps n’est pas la docstring de la fonction. C’est une expression de chaîne inutilisée, et __doc__ vaut None si aucune docstring ne figure en première instruction. Un commentaire # ne devient pas non plus la description de l’aide.

Écris le résumé au moment de définir la tâche de la fonction. Si la phrase nécessite plusieurs actions sans rapport, demande-toi si la fonction devrait être décomposée. Lorsque tu modifies les paramètres, les valeurs par défaut, les valeurs renvoyées ou les effets d’affichage, mets la docstring à jour en même temps ; les appelants s’y fient comme partie de l’interface.

Points clés

  • La docstring d’une fonction est la première instruction de son corps.
  • Utilise trois guillemets doubles et une courte phrase exprimant une instruction, terminée par un point.
  • Pour les descriptions plus longues, sépare le résumé des détails par une ligne vide.
  • Décris les entrées utiles, les unités, les valeurs par défaut, les résultats et les effets.
  • Lis la documentation stockée avec help(name) ou name.__doc__.

5.2 Décomposer un problème en fonctions

La décomposition consiste à diviser une tâche en travaux plus petits. Chaque fonction est responsable d’une tâche, avec des entrées explicites et un résultat ou un effet explicite. Le programme principal peut alors se lire comme une courte suite d’étapes nommées.

Prévoir les données avant d’écrire les corps

Pour un programme qui indique la moyenne de notes de contrôle et une note sous forme de lettre, distingue trois tâches : lire les notes, calculer une moyenne et choisir une lettre. Décide de ce que chaque fonction auxiliaire reçoit et renvoie. Garde l’affichage dans main, où les résultats se rejoignent.

def get_score(prompt):
    return float(input(prompt))

def average(a, b, c):
    return (a + b + c) / 3

def letter_grade(score):
    if score >= 90:
        return "A"
    if score >= 80:
        return "B"
    if score >= 70:
        return "C"
    return "F"

def main():
    first = get_score("Test 1: ")
    second = get_score("Test 2: ")
    third = get_score("Test 3: ")
    avg = average(first, second, third)
    print("Average:", round(avg, 1), "Grade:", letter_grade(avg))

main()

Avec les notes 78, 92 et 85, average renvoie 85,0. Ce résultat devient l’argument de letter_grade, qui renvoie « B ». L’affichage est « Average: 85.0 Grade: B ».

main coordonne la séquence ; elle n’a pas besoin de savoir comment letter_grade choisit sa réponse. Utiliser une fonction en connaissant sa tâche et son interface, sans suivre chaque instruction de son corps, relève de l’abstraction procédurale. Tu utilises déjà print de cette façon.

Fournir à l’appelant une interface claire

L’interface d’une fonction comprend son nom, ses paramètres, le résultat renvoyé et son comportement documenté. average(a, b, c) exige trois nombres et renvoie leur moyenne. Son appelant n’a pas besoin de répondre à une invite ni de récupérer du texte affiché pour obtenir ce nombre. Tu peux réécrire le calcul tout en conservant les entrées et la sortie convenues, et les appels existants continuent de fonctionner.

Utilise des noms comme calculate_total et print_receipt pour les actions, et is_even ou has_discount pour les questions booléennes. Des noms de paramètres comme price et quantity indiquent les valeurs attendues à chaque emplacement. Les noms d’une seule lettre peuvent convenir lorsque leur sens est clair, comme pour les trois entrées de average.

Transformer les éléments répétés en paramètres

Si plusieurs parties d’un programme affichent différents titres entre les mêmes lignes de signes égal, fais du titre un paramètre de print_heading(title). La structure répétée appartient à un seul corps, tandis que le texte variable appartient aux appels. Une modification ultérieure de la longueur des lignes ne demande alors qu’une seule correction.

Définis les fonctions de façon à rendre les tâches plus faciles à comprendre ou à réutiliser. Placer toutes les instructions dans une longue fonction main masque les tâches plus petites. Transformer chaque expression triviale en fonction auxiliaire utilisée une seule fois peut ajouter des noms sans améliorer la lisibilité. Un test utile consiste à vérifier si une courte phrase peut décrire chaque tâche ainsi que ses entrées et ses sorties.

Termine le fichier par l’appel effectif main() après toutes les définitions. Un programme qui ne contient que des définitions crée ses fonctions et se termine sans exécuter leurs corps.

Points clés

  • Décompose la tâche en travaux dont les entrées et les sorties sont nommées.
  • Sépare les calculs de la saisie et de l’affichage lorsqu’ils doivent être réutilisés ou vérifiés.
  • Laisse main coordonner les fonctions auxiliaires et appelle main() après les définitions.
  • Utilise des paramètres pour les parties variables du code répété.
  • Une interface stable permet aux appelants d’utiliser une fonction sans dépendre de son corps.
  • Définis les fonctions de manière à rendre le programme plus facile à comprendre.

5.3 Construire et vérifier un programme fonction par fonction

Construire plusieurs fonctions avant d’en exécuter une seule rend un échec plus difficile à localiser. Le développement incrémental consiste à écrire une petite partie, à la vérifier, puis à ajouter la suivante. Tu conserves ainsi un programme qui fonctionne tout en réduisant la quantité de nouveau code à examiner.

Utiliser un bouchon pendant la conception

Un bouchon possède l’en-tête prévu et un corps provisoire. Une docstring et pass gardent la définition valide, mais la fonction renvoie None jusqu’à son implémentation. Une valeur de retour fixe peut aider à tester l’affichage d’un appelant sans prétendre que le calcul réel fonctionne déjà.

Commence par une fonction auxiliaire de calcul dont tu peux déterminer le résultat indépendamment. Une fois qu’elle se comporte correctement, relie-la à la fonction auxiliaire suivante. Garde la saisie interactive pour le moment où les calculs pourront être vérifiés par des appels directs.

Déterminer les résultats attendus avant l’exécution

Avec les fonctions average et letter_grade, les notes 70, 75 et 72 ont une moyenne d’environ 72,33 : la note sous forme de lettre attendue est donc « C ». Vérifie les deux étapes :

print(average(70, 75, 72))
print(letter_grade(average(70, 75, 72)) == "C")

Les sorties sont « 72.33333333333333 » et « True ». La comparaison teste directement la note attendue ; regarder uniquement la sortie d’un programme sans attente indépendante peut laisser passer une réponse erronée mais plausible.

Tester les limites ainsi que les entrées ordinaires

Pour un seuil de 90, teste 90 et 89,9. La fonction de notation correcte renvoie « A » et « B ». Si sa première condition était score > 90, seule la vérification exactement au seuil révélerait que 90 passe à tort au test suivant.

Inclus une valeur courante, les seuils exacts, des valeurs proches et des entrées extrêmes que la fonction est censée traiter. Pour la fonction de notation, vérifier 70 et 0 permet de tester le seuil de réussite le plus bas et le chemin final « F ». Une vérification comme print(letter_grade(85) == "B") est facile parce que la fonction prend une valeur et renvoie son résultat.

Lire la trace d’appels et examiner la valeur reçue

Supposons que main appelle letter_grade(input("Score: ")). Saisir « 85 » envoie une chaîne dans une comparaison avec un nombre. L’erreur finale est TypeError: '>=' not supported between instances of 'str' and 'int'. La trace d’appels désigne la comparaison dans la fonction auxiliaire, tandis qu’une ligne d’appel précédente désigne main.

L’échec se produit lors de la comparaison, mais la correction doit être faite là où la saisie est préparée : convertis-la avec float() avant de la transmettre. Un print("letter_grade got", score) temporaire en première ligne aide à révéler une entrée inattendue. Si son type n’est pas clair, examine l’appelant et la conversion qu’il utilise. Supprime les affichages de débogage une fois le bug corrigé.

Associer les symptômes aux causes probables
SymptômePoint à vérifier
Un résultat vaut NoneUn return manquant ou un chemin non couvert.
Aucun effet n’apparaîtUn appel manquant ou un résultat renvoyé inutilisé.
Un résultat plausible a le mauvais sensDes arguments inversés.
NameErrorUn nom de fonction ou de variable mal orthographié ou indisponible.

Après avoir corrigé une fonction auxiliaire, relance les vérifications qui exercent les chemins concernés et l’appelant qui la relie au programme.

Points clés

  • Construis et vérifie une fonction avant d’ajouter la suivante.
  • Calcule les résultats attendus indépendamment avant de les comparer aux résultats des appels.
  • Teste les seuils exacts et les valeurs proches pour détecter les erreurs de comparaison.
  • Utilise la trace d’appels pour trouver l’échec et ses appelants.
  • Supprime les affichages de débogage temporaires une fois le problème corrigé.

Fonctions Python : exemples

5 Leçons Interactives

1

Écrire une fonction et suivre ses appels

10 étapes
Construis une fonction de salutation réutilisable, puis suis un appelant qui passe par sa fonction auxiliaire avant de revenir au programme principal.
  1. 1
    IntroductionDonner un nom à une tâche

    Une fonction te permet d’écrire une tâche utile une seule fois et de choisir quand l’exécuter. Tu vas commencer par une salutation, puis suivre un rapport qui appelle une fonction auxiliaire.

    Pendant ta lecture, distingue deux questions : « Python a-t-il créé cette fonction ? » et « Le programme l’a-t-il déjà appelée ? ». La première rend le nom disponible ; la seconde démarre le travail du corps. Cette distinction explique pourquoi un fichier rempli de définitions peut se terminer sans rien afficher.

  2. 2
    ExplicationÉcrire le corps réutilisable
    def greet():
        print("Hello!")
        print("Welcome to Python.")
    

    L’en-tête utilise def, un nom, des parenthèses et deux-points. Les deux lignes indentées de quatre espaces forment le corps. Python crée la fonction lorsque cette définition s’exécute, mais aucun des deux affichages ne s’exécute encore.

    La prochaine instruction non indentée sera hors de la fonction. L’indentation indique à Python où cette tâche se termine ; elle fait partie de la structure du programme.

  3. 3
    ExempleL’exécuter deux fois

    Ajoute ces lignes après la définition :

    greet()
    greet()
    

    Le premier appel entre dans le corps et affiche « Hello! » suivi de « Welcome to Python. ». Le second appel reprend à la première ligne du corps et affiche à nouveau les deux messages. Il y a quatre lignes de sortie.

    Les parenthèses vides restent nécessaires : greet seul désigne l’objet fonction. Il ne l’appelle pas, et print(greet) affiche une description de la fonction au lieu de la salutation.

  4. 4
    DéfiPrévoir l’effet d’un appel manquant

    Qu’affiche ce fichier ?

    def ready():
        print("Ready")
    
    ready
    print("Waiting")
    

    ---reveal---

    Il affiche seulement « Waiting ». La définition crée ready, et le nom seul désigne cette fonction sans l’exécuter. Pour afficher aussi le message, remplace ready par ready(). L’appel s’exécuterait alors avant le dernier affichage et donnerait « Ready » et « Waiting » sur des lignes distinctes.

  5. 5
    ConseilGarder des noms et des corps utilisables

    Utilise des noms comme print_receipt : des mots en minuscules reliés par des traits de soulignement qui décrivent la tâche. Évite de remplacer un nom natif. Affecter du texte à input masque la fonction : un input(...) ultérieur essaie donc d’appeler du texte et échoue.

    Un corps inachevé a besoin d’une instruction. Utilise un pass indenté comme instruction provisoire. Un commentaire seul ne constitue pas un corps, et un pass non indenté se trouverait hors de la fonction.

  6. 6
    ExempleEntrer dans un appelant
    def line():
        print("----------")
    
    def banner():
        line()
        print("  REPORT")
        line()
    
    print("Start")
    banner()
    print("End")
    

    Les deux définitions s’exécutent d’abord sans rien afficher. L’instruction au premier niveau affiche « Start », puis banner() entre dans le corps de la bannière. Sa première ligne appelle line : la bannière doit donc attendre que cette fonction auxiliaire affiche ses tirets. Ne passe pas au titre avant que la fonction auxiliaire soit terminée.

  7. 7
    ExplicationReprendre un niveau à la fois

    Lorsque line se termine, l’exécution reprend à l’affichage du titre dans banner. La bannière appelle ensuite line une seconde fois, ce qui produit la seconde ligne de tirets. Lorsque la bannière se termine, le programme principal reprend et affiche « End ».

    La pile d’appels de Python enregistre les appels non terminés et leurs points de retour. Pendant que la fonction auxiliaire s’exécute, la bannière et le programme principal attendent. Un suivi sur papier peut marquer ces points de retour et noter la sortie au moment où chaque affichage s’exécute.

  8. 8
    DéfiSuivre un autre appel de fonction auxiliaire

    Quel est l’ordre de la sortie ?

    def inner():
        print("I")
    
    def outer():
        print("O")
        inner()
        print("P")
    
    outer()
    print("Q")
    

    ---reveal---

    Les lignes sont « O », « I », « P » et « Q ». Le corps externe affiche d’abord, attend inner, puis reprend à son affichage suivant. Ce n’est qu’après la fin de outer que la dernière instruction au premier niveau s’exécute. L’ordre des définitions ne détermine pas à lui seul l’ordre de la sortie.

  9. 9
    DéfiDéplacer une définition sans risque

    Un fichier définit show avec un corps qui appelle border. Il définit ensuite border, puis se termine par une boucle qui appelle show() deux fois. La définition plus basse de la fonction auxiliaire provoquera-t-elle une erreur, et combien de fois border s’exécute-t-elle ?

    ---reveal---

    Le programme fonctionne : les deux définitions ont été exécutées avant que la boucle appelle show. Chaque appel entre dans show à la première ligne de son corps et atteint un appel à border : la fonction auxiliaire s’exécute donc deux fois. Déplacer la boucle au-dessus de la définition de la fonction auxiliaire rendrait son nom indisponible au premier moment où il est nécessaire.

  10. 10
    RécapitulatifLire à partir de la première instruction exécutée

    Lorsque tu suis l’exécution d’un programme avec des fonctions :

    • Vérifie l’en-tête et l’indentation pour repérer chaque corps.
    • Commence par les instructions au premier niveau et n’entre dans un corps que par un appel.
    • Marque l’instruction suivante de l’appelant avant de suivre une fonction auxiliaire.
    • Note la sortie lorsque son affichage s’exécute.

    Si un appel échoue, lis la dernière erreur de la trace d’appels, puis examine la ligne du corps en échec et l’appelant qui y a conduit. Le chemin des appels est souvent la clé pour comprendre l’erreur.

2

Renseigner les emplacements des paramètres

13 étapes
Associe les valeurs par position ou par nom, puis examine les valeurs par défaut créées au moment de la définition.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionRéutiliser une tâche avec différentes valeurs
  2. 2
    ExempleAssocier la première et la deuxième entrée
  3. 3
    ExplicationÉvaluer les arguments avant le corps
  4. 4
    DéfiVérifier le nombre d’arguments
  5. 5
    ExplicationUtiliser des noms pour montrer les rôles
  6. 6
    DéfiCorriger un emplacement renseigné deux fois
  7. 7
    ConseilLire les options nommées des fonctions natives
  8. 8
    ExempleRendre le choix courant facultatif
  9. 9
    DéfiSauter un choix facultatif grâce au nom
  10. 10
    Point cléUne valeur par défaut garde sa valeur à la création
  11. 11
    ExempleComprendre pourquoi une liste par défaut conserve ses éléments
  12. 12
    DéfiCombiner valeurs par défaut et entrées nommées
  13. 13
    RécapitulatifComparer l’appel à l’en-tête
3

Suivre les valeurs jusqu’à l’appelant

14 étapes
Distingue les affichages des résultats, puis construis des branches, des recherches et des appels imbriqués qui renvoient les valeurs nécessaires.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionObserver ce que reçoit l’appelant
  2. 2
    ExempleRemplacer l’appel par son résultat
  3. 3
    ExplicationDistinguer l’affichage du résultat
  4. 4
    DéfiTrouver la valeur utilisée dans l’addition
  5. 5
    ConseilVérifier où l’appel s’exécute
  6. 6
    ExempleS’arrêter à la première note correspondante
  7. 7
    DéfiTraiter l’entrée entre les branches
  8. 8
    Point cléLaisser une comparaison répondre à la question
  9. 9
    ExempleRenvoyer un diviseur trouvé
  10. 10
    DéfiCorriger un résultat positif renvoyé trop tôt
  11. 11
    ExempleDépaqueter un résultat regroupé
  12. 12
    ExempleTransmettre un résultat interne vers l’extérieur
  13. 13
    DéfiCombiner un retour anticipé et un résultat
  14. 14
    RécapitulatifSuivre ensemble les chemins et les valeurs renvoyées
4

Suivre les noms et les objets partagés

11 étapes
Distingue les noms locaux des noms globaux, puis rends explicite dans l’appelant un total qui change.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionSe demander où appartient le nom
  2. 2
    ExempleDonner à chaque appel son propre compteur
  3. 3
    ExplicationDistinguer les noms masqués
  4. 4
    DéfiRendre explicite la mise à jour dans l’appelant
  5. 5
    ExempleSuivre une liste partagée par un paramètre
  6. 6
    ExempleLire une variable globale sans déclaration
  7. 7
    Point cléL’affectation détermine la portée locale dès le départ
  8. 8
    DéfiChoisir la portée d’une mise à jour
  9. 9
    LienFaire passer la valeur changeante par l’appel
  10. 10
    DéfiDistinguer mutation et réaffectation
  11. 11
    RécapitulatifNommer l’opération avant de prévoir son effet
5

Concevoir et vérifier un compte rendu de notes

12 étapes
Documente une fonction auxiliaire, prévois ses entrées et ses résultats, puis vérifie les seuils et les données de l’appelant avant de relier les parties du programme.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionConstruire un programme à partir de tâches claires
  2. 2
    ExemplePlacer la description là où l’aide peut la trouver
  3. 3
    ExplicationAjouter les détails qui influent sur un appel
  4. 4
    DéfiTrouver la documentation manquante
  5. 5
    ExplicationChoisir une tâche pour chaque fonction auxiliaire
  6. 6
    ExempleRelier les fonctions auxiliaires dans main
  7. 7
    DéfiSéparer le calcul de l’affichage
  8. 8
    ConseilConserver un programme qui fonctionne pendant la construction
  9. 9
    ExempleVérifier un seuil qui peut révéler un bug
  10. 10
    DéfiTrouver où un type incorrect entre
  11. 11
    DéfiFaire concorder la documentation et une vérification
  12. 12
    RécapitulatifUtiliser l’interface pour guider les vérifications

Fonctions Python : QCM

40 Questions Pratiques en 4 séries

Série 1 : Suivre les entrées, la portée et les résultats manquants10 Questions Pratiques

Question 1 sur 10

Comment compléter ce corps de fonction inachevé pour que le fichier soit valide mais que la fonction ne fasse encore rien ?

def print_ticket():
    # Work to be added later
  1. Ajouter un pass non indenté sous le commentaire.
  2. Ajouter un autre commentaire indenté en dessous.
  3. Ajouter un pass indenté sous le commentaire.
  4. Ajouter un print_ticket() non indenté en dessous.
Afficher la réponseMasquer la réponse
Réponse : C
Un pass indenté est une instruction valide pour le corps qui ne fait rien. Les commentaires seuls ne constituent pas le corps requis : ajouter un autre commentaire laisse donc la définition incomplète. Une instruction non indentée se trouve hors de la fonction et ne peut pas fournir son corps manquant.

Question 2 sur 10

Qu’affiche ce programme ?

def show_scaled(value, factor):
    print(value * factor)

entry = "6"
show_scaled(entry, 3)
  1. « 666 »
  2. « 18 »
  3. « 6 6 6 »
  4. « 9 »
Afficher la réponseMasquer la réponse
Réponse : A
L’argument entry contient du texte, et Python répète ce texte lorsqu’il est multiplié par l’entier 3. La sortie est « 666 », sans espaces ajoutées. Pour obtenir 18, il faudrait convertir le texte en nombre avant la multiplication ; le nom du paramètre n’effectue pas cette conversion.

Question 3 sur 10

Quelle valeur est renvoyée ?

step = 4

def advance(position, amount=step):
    return position + amount

step = 9
result = advance(10)
  1. 19
  2. 9
  3. 10
  4. 14
Afficher la réponseMasquer la réponse
Réponse : D
L’expression de la valeur par défaut est évaluée lorsque def s’exécute, alors que step vaut 4. Omettre amount ajoute donc 4 à 10 et renvoie 14. Modifier ensuite step à 9 ne met pas à jour la valeur par défaut stockée ; pour obtenir 19, il faudrait transmettre explicitement la nouvelle valeur.

Question 4 sur 10

Quelle modification unique permet à result de contenir 16 sans l’afficher dans la fonction auxiliaire ?

def square(n):
    print(n * n)

result = square(4)
  1. Remplacer le corps par return print(n * n).
  2. Remplacer le corps par return n * n.
  3. Ajouter return après l’affichage existant.
  4. Remplacer l’appel par result = print(square(4)).
Afficher la réponseMasquer la réponse
Réponse : B
Renvoyer n * n transmet directement 16 à l’affectation sans affichage dans la fonction auxiliaire. return print(n * n) affiche toujours le nombre et renvoie le résultat de print, qui est None. Un return seul après un affichage donne aussi None : il ne fournit donc pas le nombre calculé.

Question 5 sur 10

Qu’est-ce qui est affiché ?

def pack(total, size):
    return total // size, total % size

def double(n):
    return n * 2

boxes, spare = pack(29, 6)
print(double(boxes) + spare)
  1. « 12 »
  2. « 9 »
  3. « 14 »
  4. « 13 »
Afficher la réponseMasquer la réponse
Réponse : D
Répartir 29 en groupes de 6 renvoie le tuple (4, 5) : boxes vaut donc 4 et spare vaut 5. Doubler le nombre de boîtes donne 8, puis ajouter 5 affiche « 13 ». Obtenir 14 revient à inverser les deux valeurs dépaquetées avant de doubler, ce qui ne respecte pas l’ordre de retour.

Question 6 sur 10

Qu’est-ce qui est affiché après les deux appels ?

def add_guest(guests):
    guests.append("Sol")

def replace_guests(guests):
    guests = ["Tao"]

party = ["Ren"]
add_guest(party)
replace_guests(party)
print(party)
  1. ['Tao']
  2. ['Ren']
  3. ['Ren', 'Sol']
  4. ['Ren', 'Sol', 'Tao']
Afficher la réponseMasquer la réponse
Réponse : C
add_guest ajoute « Sol » à la même liste que celle désignée par party. replace_guests ne fait que réaffecter son paramètre local à une nouvelle liste : party désigne donc toujours ['Ren', 'Sol']. S’attendre à ['Tao'] revient à confondre la redirection du nom local avec le remplacement de la référence de l’appelant.

Question 7 sur 10

Que se passe-t-il lorsque inspect() est appelée ?

count = 11

def inspect():
    print(count)
    count = 2

inspect()
  1. Elle déclenche UnboundLocalError avant d’afficher une valeur.
  2. Elle affiche « 11 » puis donne la valeur 2 au count global.
  3. Elle affiche « 11 » puis crée un count local valant 2.
  4. Elle affiche « 2 » car l’affectation locale s’exécute d’abord.
Afficher la réponseMasquer la réponse
Réponse : A
L’affectation à count le rend local dans tout le corps, y compris lors de l’affichage précédent. Ce nom local n’a pas de valeur lorsque l’instruction d’affichage essaie de le lire : l’appel déclenche donc UnboundLocalError. Python n’utilise pas d’abord le 11 global avant de passer à la portée locale lorsqu’il atteint l’affectation.

Question 8 sur 10

Que contient show.__doc__ ?

def show():
    value = 2
    """Display the current value."""
    print(value)
  1. La phrase « Display the current value. »
  2. None
  3. Le nombre 2
  4. La ligne source print(value)
Afficher la réponseMasquer la réponse
Réponse : B
La chaîne suit une affectation : elle n’est donc pas la première instruction et ne devient pas la docstring de la fonction. Sans docstring reconnue, show.__doc__ vaut None. Les triples guillemets ne suffisent pas à eux seuls ; déplace la description au-dessus de l’affectation pour la stocker comme documentation.

Question 9 sur 10

Trois parties d’un programme affichent un titre entre des lignes de séparation identiques. Quelle modification supprime la logique répétée tout en conservant des titres différents ?
  1. Créer une fonction distincte sans paramètre pour chaque titre.
  2. Stocker chaque titre dans une variable globale lue par une fonction d’affichage.
  3. Placer les trois blocs inchangés dans main.
  4. Écrire print_heading(title) et lui transmettre chaque titre.
Afficher la réponseMasquer la réponse
Réponse : D
Une fonction peut contenir la structure commune de séparation et de titre, tandis qu’un paramètre fournit chaque titre différent. Une modification ultérieure du séparateur ne demande alors qu’une modification du corps. Déplacer les trois blocs inchangés dans main ne fait que déplacer la répétition et exige toujours plusieurs modifications pour changer ce comportement commun.

Question 10 sur 10

Une catégorie doit être « complète » à partir de 50 et « partielle » en dessous de 50. Quelle paire d’entrées de test révèle le mieux un test > 50 écrit par erreur ?
  1. 50 et 49
  2. 51 et 52
  3. 25 et 30
  4. 49 et 48
Afficher la réponseMasquer la réponse
Réponse : A
L’entrée 50 doit emprunter le chemin « complète », tandis que 49 doit emprunter le chemin « partielle ». Les tester vérifie le seuil exact et le cas immédiatement inférieur, ce qui révèle une comparaison stricte qui rejette 50. Les entrées 51 et 52 satisfont les deux comparaisons et ne révèlent donc pas l’erreur au seuil.
Série 2 : Lire les appels et suivre leurs résultats10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Quelle sortie ce programme produit-il ?

def announce():
    print("Open")

print("Ready")
  1. « Open » puis « Ready ».
  2. « Ready » seul sur une ligne.
  3. « Ready » puis « Open » en dessous.
  4. Aucune sortie n’est affichée.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Quel est l’ordre de la sortie ?

def mark():
    print("M")

def stage():
    print("S")
    mark()
    print("T")

print("R")
stage()
  1. « M », « S », « T », « R »
  2. « R », « M », « S », « T »
  3. « R », « S », « T », « M »
  4. « R », « S », « M », « T »
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Qu’affiche cet appel ?

def describe_trip(origin, destination):
    print(origin, "to", destination)

describe_trip("Mesa", "Salem")
  1. « Mesa to Salem »
  2. « Salem to Mesa »
  3. « origin to destination »
  4. « Mesa Salem to »
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Comment appeler cette fonction en utilisant « Inez » pour la personne et « West » pour la salle ?

def show_booking(person, room):
    print(person, room)
  1. show_booking(person="Inez", "West")
  2. show_booking("Inez", person="West")
  3. show_booking(room="West", person="Inez")
  4. show_booking(name="Inez", room="West")
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Qu’est-ce qui est affiché ?

def label(text, copies=2):
    print(text * copies)

label("Go")
  1. « Go »
  2. « GoGo »
  3. « Go2 »
  4. « Go Go »
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Qu’affiche la dernière ligne ?

def triple(value):
    print(value * 3)

answer = triple(4)
print(answer)
  1. « None »
  2. « 12 »
  3. « 4 »
  4. Rien ; la dernière ligne est sautée.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Que renvoie cette fonction pour first_factor(25) ?

def first_factor(n):
    for candidate in range(2, n):
        if n % candidate == 0:
            return candidate
        return n
  1. 5 après avoir vérifié les candidats de 2 à 5.
  2. None parce que le premier candidat échoue.
  3. 25 après avoir vérifié tous les candidats.
  4. 25 après avoir vérifié seulement le candidat 2.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Quelles sont les deux lignes de sortie ?

level = 7

def show_level():
    level = 3
    print(level)

show_level()
print(level)
  1. « 3 », puis « 3 »
  2. « 7 », puis « 3 »
  3. « 3 », puis « 7 »
  4. « 7 », puis « 7 »
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Quel est le rôle de la première chaîne dans cette fonction ?

def square(n):
    """Return the square of n."""
    return n * n
  1. Une description stockée, affichée par help(square).
  2. Le texte renvoyé par chaque appel à square.
  3. Un message affiché avant la multiplication.
  4. Une valeur par défaut utilisée lorsque n est omis.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Un programme lit une distance, la convertit et affiche un message. Quelle interface permet de vérifier la conversion sans effectuer de saisie ?
  1. Une fonction de conversion sans paramètres qui lit la distance.
  2. Une fonction de conversion qui prend la distance et renvoie la valeur convertie.
  3. Une fonction de conversion qui prend la distance et affiche la valeur convertie.
  4. Une fonction de conversion sans paramètres qui modifie une distance globale.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 3 : Diagnostiquer les appels et corriger le comportement du programme10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Pourquoi ce programme fonctionne-t-il alors que tick est définie sous report ?

def report():
    tick()

def tick():
    print("Done")

report()
  1. Python exécute chaque corps de fonction une fois avant tout appel.
  2. La définition de report déplace tick au-dessus d’elle.
  3. Le corps de report est copié dans la définition de tick.
  4. Les deux définitions s’exécutent avant que report() appelle tick.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Quelle valeur d’argument parvient à width ?

def show_width(width):
    print(width)

base = 8
show_width(base + 3)
  1. 8
  2. 11
  3. Le texte « base + 3 »
  4. Aucune valeur car les noms diffèrent.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Pourquoi cet appel échoue-t-il ?

def mark_pages(first, last):
    print(first, last)

mark_pages(4, first=9)
  1. L’argument nommé suit un argument positionnel.
  2. Deux arguments entiers ne peuvent pas être utilisés ensemble.
  3. first reçoit deux valeurs et last n’en reçoit aucune.
  4. Les noms des arguments doivent correspondre aux variables de l’appelant.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Quelles sont les deux listes affichées ?

def collect(value, bucket=[]):
    bucket.append(value)
    return bucket

print(collect("red"))
print(collect("blue", []))
  1. ['red'], puis ['blue']
  2. ['red'], puis ['red', 'blue']
  3. ['red', 'blue'], puis ['blue']
  4. ['blue'], puis ['red', 'blue']
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Quelle est la sortie complète ?

def shift(n):
    return n + 2
    print("shifted")

shift(5)
print("done")
  1. « shifted », puis « done »
  2. « 7 », puis « done »
  3. « done » uniquement
  4. « shifted » uniquement
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Une fonction doit renvoyer True exactement lorsqu’un entier est premier. Pourquoi ce corps accepte-t-il 35 à tort ?

def is_prime(n):
    if n < 2:
        return False
    for d in range(2, n):
        if n % d == 0:
            return False
        else:
            return True
  1. Il essaie tous les candidats mais saute 5.
  2. Il renvoie False au candidat 5.
  3. Il considère comme premier tout nombre impair inférieur à 2.
  4. Il renvoie True au candidat 2 avant d’essayer 5.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Qu’est-ce qui est affiché ?

total = 2

def add(amount):
    global total
    total = total + amount
    return total

first = add(4)
second = add(first)
print(total, second)
  1. « 6 12 »
  2. « 12 12 »
  3. « 8 8 »
  4. « 6 6 »
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Une fonction fait passer sa durée par défaut de 15 minutes à 20 minutes, avec le même calcul et les mêmes unités. Quelle modification de la documentation est nécessaire ?
  1. Mettre à jour la valeur par défaut documentée du paramètre facultatif à 20 minutes.
  2. Renommer la fonction dans la docstring pour mentionner 20 minutes.
  3. Déplacer la docstring après le calcul pour documenter son nouveau résultat.
  4. Supprimer la description du paramètre puisque l’en-tête montre son nom.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Une fonction auxiliaire numérique conserve le même nom, les mêmes paramètres, valeurs renvoyées et effets documentés après simplification de son corps. Pourquoi les appelants existants peuvent-ils rester inchangés ?
  1. Les appelants reçoivent toutes les variables locales du nouveau corps.
  2. Python stocke l’ancien corps jusqu’à la réécriture de tous les appelants.
  3. Les appelants utilisent une interface dont le comportement est conservé.
  4. Une docstring pousse Python à corriger automatiquement chaque appel.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Une fonction auxiliaire numérique échoue à if score >= 60: après que l’appelant a transmis input("Score: "). Quelle correction traite le type de la saisie ?
  1. Remplacer la comparaison par score >= "60".
  2. Convertir la saisie avec float() avant d’appeler la fonction auxiliaire.
  3. Ajouter un affichage après la comparaison pour montrer score.
  4. Supprimer le paramètre et lire un score global à la place.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 4 : Combiner les règles des fonctions dans de nouvelles situations10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Comment nommer une fonction qui affiche un reçu de paiement dans le style habituel de Python ?
  1. print_receipt
  2. print-receipt
  3. 2print_receipt
  4. print receipt
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Qu’est-ce qui est affiché ?

def outer():
    inner()
    print("Y")

outer()

def inner():
    print("X")
  1. « X », puis « Y »
  2. « Y » uniquement, puis une NameError
  3. Aucune sortie ; une NameError se produit dans outer.
  4. « X » uniquement, puis une NameError
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Quelle est la sortie complète, sauts de ligne compris ?

print("N", "S", sep="/", end="|")
print("E", "W", sep="-")
  1. Deux lignes : « N/S| » puis « E-W »
  2. Une ligne : « N/S|E-W »
  3. Une ligne : « N S|E W »
  4. Deux lignes : « N/S » puis « |E-W »
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Un nouvel appel qui omet items doit commencer avec une nouvelle liste, mais une liste fournie doit être complétée en place. Quel corps de remplacement est correct ?

def add_code(code, items=None):
    # replacement body
  1.     items = []
        items.append(code)
        return items
    
  2.     if items == []:
            items = []
        items.append(code)
        return items
    
  3.     if items is None:
            return []
        items.append(code)
        return items
    
  4.     if items is None:
            items = []
        items.append(code)
        return items
    
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Quelle modification permet à cette fonction de renvoyer le premier candidat correspondant, ou None seulement après l’échec de tous les candidats ?

def find_divisor(n):
    for d in range(3, n):
        if n % d == 0:
            return d
        else:
            return None
  1. Remplacer return None par return False dans le else.
  2. Supprimer le else et placer return None après la boucle.
  3. Placer les deux instructions return après la boucle.
  4. Déplacer return d avant le test if dans la boucle.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Qu’affiche la dernière ligne ?

def change(values):
    values.append("B")
    values = ["C"]
    values.append("D")
    return values

original = ["A"]
result = change(original)
print(original, result)
  1. ['A'] ['C', 'D']
  2. ['A', 'B', 'D'] ['C']
  3. ['C', 'D'] ['C', 'D']
  4. ['A', 'B'] ['C', 'D']
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Comment l’appelant peut-il mettre à jour stock explicitement sans que la fonction auxiliaire modifie une variable globale ?

stock = 18

def remove(stock, amount):
    return stock - amount

# caller statement
  1. remove(stock, 4)
  2. stock = remove(4, stock)
  3. stock = remove(stock, 4)
  4. remove(stock=4, amount=stock)
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Une fonction auxiliaire provisoire ne contient qu’une docstring et pass. Son appelant ajoute le résultat de la fonction auxiliaire à 7 et obtient TypeError. Que faut-il implémenter ensuite ?
  1. Renvoyer le résultat numérique promis par la tâche de la fonction auxiliaire.
  2. Afficher le nombre promis avant l’instruction pass.
  3. Déplacer la docstring sous pass pour la rendre exécutable.
  4. Répéter l’appel à la fonction auxiliaire avant d’ajouter son résultat à 7.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Qu’est-ce qui est affiché ?

def add_fee(amount):
    return amount + 3

def twice(amount):
    return amount * 2

print(twice(add_fee(5)))
  1. « 13 »
  2. « 8 »
  3. « 10 »
  4. « 16 »
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Qu’est-ce qui est affiché ?

rate = 2

def scale(value, factor=rate):
    return value * factor

def reset():
    global rate
    rate = 5

reset()
print(scale(3), scale(3, rate))
  1. « 15 15 »
  2. « 6 6 »
  3. « 6 15 »
  4. « 15 6 »
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Tu bloques sur ton propre exercice ? Aide aux Devoirs

Mots-Clés

56 Mots-Clés, chacun avec sa définition

A

Abstraction procédurale
L’abstraction procédurale permet au code d’utiliser une fonction à partir de sa tâche convenue sans dépendre de la façon dont son corps l’accomplit.
Un appelant peut utiliser letter_grade(avg) sans suivre chaque comparaison de seuil dans le corps.
Affichage de débogage
Un affichage de débogage montre temporairement une valeur pendant la recherche d’un bug et est supprimé une fois la recherche terminée.
Un affichage en première ligne peut révéler le score inattendu qui parvient à une fonction auxiliaire depuis son code appelant.
Appel de fonction
Un appel de fonction est une expression qui exécute une fonction, écrite avec son nom et des parenthèses contenant les éventuels arguments.
La ligne greet() exécute la salutation, tandis qu’une ligne contenant seulement greet ne l’exécute pas.
Appel imbriqué
Un appel imbriqué est un appel de fonction placé dans l’expression d’un argument d’un autre appel, dont le résultat est nécessaire avant l’exécution de l’appel externe.
Dans print(to_fahrenheit(add(10, 15))), l’addition s’exécute avant la conversion, puis vient l’affichage.
Appelant
Un appelant est le code qui appelle une fonction et attend qu’elle se termine avant de continuer après l’appel.
Lorsque banner() appelle line(), le corps de la bannière est l’appelant de la fonction qui trace une ligne.
Argument
Un argument est une valeur fournie dans un appel de fonction, après l’évaluation de toute expression qui produit cette valeur.
Dans area(side + 1, 2), Python calcule le premier argument avant de commencer le corps de la fonction d’aire.
Argument nommé
Un argument nommé indique dans un appel le paramètre auquel il est destiné : l’association dépend donc du nom plutôt que de la position.
L’appel describe_pet(name="Milo", animal="cat") renseigne les paramètres dans un ordre lisible.
Argument positionnel
Un argument positionnel est associé à un paramètre selon son ordre dans un appel, la première valeur renseignant le premier emplacement.
Pour describe_pet(animal, name), describe_pet("cat", "Milo") place « cat » dans animal.

B

Bouchon
Un bouchon est une fonction inachevée avec son en-tête prévu et un corps provisoire, qui permet aux appelants de s’exécuter pendant le développement.
Une docstring et pass créent un bouchon valide, même si ses appels renvoient toujours None jusqu’à son implémentation.

C

Chemin de retour
Un chemin de retour est un parcours dans les branches et les boucles d’une fonction qui atteint une instruction return ou la fin du corps.
Une fonction de signe a besoin d’un résultat pour zéro ainsi que de chemins qui renvoient des indications positive et négative.
Constante
Une constante est un paramètre destiné à rester fixe ; la convention Python écrit en majuscules les noms des constantes définies au niveau du fichier.
Une fonction peut lire TAX_RATE = 0.25 pour calculer une taxe sans déclarer ce nom global.
Corps de la fonction
Le corps de la fonction est le bloc indenté d’instructions sous son en-tête, suivi depuis le début à chaque appel.
Deux lignes print indentées sous def greet(): appartiennent toutes deux au corps de la fonction.

D

Décomposition
La décomposition divise un problème en tâches plus petites qui peuvent chacune être implémentées, comprises et vérifiées sous forme de fonction.
Un programme de compte rendu de notes sépare la lecture des notes, le calcul d’une moyenne et le choix d’une note sous forme de lettre.
Définition de fonction
Une définition de fonction est une instruction def avec un en-tête et un corps indenté qui crée une fonction sous un nom.
Python crée greet à def greet(): et attend un appel avant d’exécuter son corps.
Dépaquetage
Le dépaquetage affecte les valeurs distinctes d’un résultat regroupé aux noms correspondants, en conservant leur ordre d’origine.
Si share(17, 5) renvoie 17 // 5, 17 % 5, l’affectation each, left = share(17, 5) place 3 dans each et 2 dans left.
Développement incrémental
Le développement incrémental construit un programme par petits ajouts, en vérifiant chaque partie avant d’y relier d’autres travaux.
Vérifier d’abord une fonction auxiliaire de moyenne réduit la quantité de code à examiner lorsqu’un compte rendu de notes ultérieur présente une erreur.
Docstring
Une docstring est la chaîne placée comme première instruction du corps d’une fonction, stockée avec celle-ci pour décrire son utilisation aux appelants.
La docstring d’une fonction de conversion peut expliquer les unités de température en entrée et en sortie avant que quiconque lise la formule.
Docstring d’une ligne
Une docstring d’une ligne est une courte phrase exprimant une instruction, placée par convention entre trois guillemets doubles et terminée par un point.
« Renvoyer l’aire d’un rectangle. » décrit la tâche sans répéter la signature de la fonction.
Docstring multiligne
Une docstring multiligne comprend un résumé, une ligne vide et des détails supplémentaires sur les entrées, les valeurs par défaut, les résultats et les effets.
Une fonction de partage d’addition peut documenter que tip_rate=0.2 est une fraction de l’addition, et non 20.

E

En-tête
L’en-tête d’une fonction est la première ligne contenant def, le nom de la fonction, les parenthèses des paramètres et deux-points.
Dans def print_line(length):, l’en-tête nomme la tâche et son entrée avant que le corps commence.

É

État caché
L’état caché est une information dont une fonction dépend ou qu’elle modifie sans la montrer par ses paramètres et son résultat renvoyé.
Une fonction qui met à jour un total global nécessite que ce total soit préparé avant une vérification indépendante.

F

Flot d’exécution
Le flot d’exécution est l’ordre dans lequel les instructions s’exécutent, y compris les passages dans les fonctions et les retours à leurs appelants.
Un rapport peut afficher « Start », entrer dans banner(), terminer ses appels de fonctions auxiliaires, puis afficher « End ».
Fonction
Une fonction est un bloc de code nommé qui accomplit une tâche lorsqu’il est appelé, permettant à un programme de réutiliser la même logique.
Un programme de reçus peut appeler print_receipt() chaque fois qu’il doit afficher un autre reçu.
Fonction avec valeur de retour
Une fonction avec valeur de retour renvoie un résultat utile que le code appelant peut utiliser dans une expression, une affectation ou une condition.
Une fonction de conversion de température qui renvoie un nombre peut alimenter un tableau affiché ou une comparaison à une limite.
Fonction booléenne
Une fonction booléenne répond à une question par oui ou par non en renvoyant True ou False, souvent directement à partir d’une comparaison.
Le corps return n % 2 == 0 permet d’utiliser is_even(n) directement comme condition d’un if.
Fonction help
La fonction help affiche des informations sur une fonction, notamment sa signature et sa docstring stockée lorsqu’elle existe.
Utilise help(to_fahrenheit) pour examiner la fonction de conversion sans lui fournir d’abord une température.
Fonction main
Une fonction main coordonne les petites tâches d’un programme en reliant les entrées, les résultats des fonctions auxiliaires et l’affichage final.
Un appel final à main() exécute les étapes d’un compte rendu de notes après l’exécution de toutes les définitions des fonctions auxiliaires.

I

Instruction global
L’instruction global fait qu’un nom dans une fonction désigne la liaison au niveau du fichier pour les lectures et les affectations ultérieures.
Place global total avant que la fonction utilise total pour mettre à jour un compteur cumulé partagé.
Instruction pass
L’instruction pass est une instruction provisoire qui n’effectue aucune action et permet au corps d’une fonction en cours de conception d’être valide en Python.
Une fonction contenant seulement pass peut être appelée pendant que son comportement réel d’affichage est encore en cours d’écriture.
Instruction return
Une instruction return termine l’appel de fonction en cours et transmet son résultat à l’appelant ; sans expression, elle transmet None.
L’instruction return width * height permet à l’appelant de stocker une aire ou de l’utiliser dans un autre calcul.
Interface
L’interface d’une fonction comprend son nom, ses paramètres, le résultat renvoyé et son comportement documenté : c’est l’accord utilisé par ses appelants.
Un calcul peut être réécrit sans modifier les appels si l’interface fournit toujours le même résultat promis.

M

Masquage
Le masquage se produit lorsqu’un nom local cache un nom global de même orthographe dans une fonction sans remplacer la liaison globale.
Si une fonction auxiliaire affecte localement x = 5 alors que x = 10 est global, le x de la fonction auxiliaire donne 5 et un x global ultérieur donne toujours 10.
Mutation
La mutation modifie le contenu d’un objet existant, de sorte qu’un autre nom désignant le même objet peut observer ce changement.
Ajouter « Ben » par l’intermédiaire d’un paramètre de type liste modifie la liste d’invités transmise par l’appelant.

N

None
None est la valeur spéciale de Python qui signifie « aucune valeur » ; elle sert aussi à signaler qu’une entrée facultative a été omise.
Avec basket=None, la fonction peut créer une nouvelle liste dans if basket is None:.

P

Paramètre
Un paramètre est un nom dans l’en-tête d’une fonction qui reçoit la valeur d’un argument comme variable locale pendant un appel.
L’en-tête def area(width, height): donne à chaque appel de la fonction d’aire des noms locaux pour ses deux dimensions.
Paramètre end
Le paramètre end de print contrôle le texte ajouté après les valeurs affichées ; il utilise un saut de ligne par défaut.
Utiliser end="..." permet à l’affichage suivant de continuer après les points au lieu de commencer une nouvelle ligne.
Paramètre facultatif
Un paramètre facultatif a une valeur par défaut : un appel peut l’omettre ou remplacer cette valeur par un argument explicite.
Un appel à une fonction de commande de café peut définir milk="oat" tout en laissant à sa valeur par défaut un paramètre facultatif précédent qui indique le nombre de doses.
Paramètre obligatoire
Un paramètre obligatoire n’a pas de valeur par défaut et doit recevoir une valeur dans chaque appel valide, par position ou par un nom accepté.
Avec def greet(name, greeting="Hello"):, omettre name provoque une erreur d’argument manquant.
Paramètre sep
Le paramètre sep de print contrôle le texte inséré entre les valeurs affichées ; il utilise une espace par défaut.
L’appel print("a", "b", "c", sep="-") affiche les trois lettres sous la forme « a-b-c ».
Passage d’arguments mixte
Le passage d’arguments mixte fournit certaines valeurs par position et d’autres par nom, les valeurs positionnelles venant en premier.
Dans describe_pet("cat", name="Milo"), le premier emplacement est renseigné par position et le second par nom.
Pile d’appels
La pile d’appels est le registre tenu par Python des appels commencés mais non terminés, y compris l’endroit où leurs appelants reprennent.
Pendant qu’une fonction auxiliaire de ligne s’exécute dans un appel de bannière, les deux appels non terminés occupent une place dans la pile d’appels.
Portée
La portée est la partie d’un programme où un nom peut être utilisé ; elle détermine quelle variable une référence désigne.
Un nom créé seulement dans make_greeting() n’est pas disponible pour un affichage au premier niveau après l’appel.
Procédure
Une procédure est une fonction utilisée pour un effet, comme l’affichage, qui ne fournit aucun résultat utile au-delà de None.
Une fonction qui affiche une salutation peut montrer « Hello! » correctement même si son appelant reçoit None.

R

Réaffectation
La réaffectation donne une nouvelle valeur ou un nouvel objet à un nom existant ; réaffecter un paramètre modifie cette liaison locale.
La ligne points = points + 10 modifie le paramètre local et laisse le score de l’appelant inchangé.
Résultat attendu
Un résultat attendu est une réponse calculée indépendamment avant une vérification, utilisée pour juger ce qu’une fonction renvoie réellement.
Calculer une moyenne à la main permet de repérer une sortie de programme qui semble plausible mais est incorrecte.
Retour anticipé
Un retour anticipé termine une fonction avant l’exécution de ses instructions ultérieures, souvent lorsqu’une branche ou une recherche a déjà trouvé la réponse.
Une recherche de diviseur renvoie 7 pour 91 dès que ce candidat le divise sans reste, ce qui termine aussi la boucle.

T

Test aux limites
Un test aux limites vérifie une entrée exactement à un seuil de décision, souvent avec une valeur proche qui emprunte l’autre chemin.
Les notes 90 et 89,9 révèlent une condition de notation qui utilise accidentellement > au lieu de >=.
Trace d’appels
Une trace d’appels est un rapport d’erreur qui montre le chemin des appels non terminés, la ligne en échec, puis le type et le message de l’erreur.
Dans une trace d’appels, lis d’abord la dernière erreur, puis examine la ligne en échec de la fonction auxiliaire et l’appelant qui a fourni ses entrées.
Tuple
Un tuple est une séquence regroupée de valeurs ; des valeurs séparées par des virgules dans un return forment un tuple unique comme résultat pour l’appelant.
L’instruction return total // people, total % people regroupe une part et un reste.
TypeError
Une TypeError signale une opération inadaptée sur une valeur ou un appel avec une combinaison d’arguments invalide.
Appeler une fonction à deux paramètres avec un seul argument déclenche une TypeError pour l’entrée manquante.

U

UnboundLocalError
Une UnboundLocalError se produit lorsqu’une fonction essaie de lire un nom local avant que ce nom ait une valeur.
Une affectation ultérieure à count rend aussi local un print(count) précédent, même si une variable globale existe.

V

Valeur de retour
Une valeur de retour est le résultat qu’un appel fournit à son appelant, qui peut le stocker, le tester ou le transmettre à une autre opération.
Après area = rectangle_area(4, 2.5), area contient le résultat renvoyé 10,0 pour une utilisation ultérieure.
Valeur par défaut
Une valeur par défaut est une valeur stockée pour un paramètre lorsque la définition s’exécute et utilisée lorsqu’un appel omet l’argument correspondant.
Dans def greet(name, greeting="Hello"):, un appel peut omettre la salutation tout en fournissant le nom.
Valeur par défaut mutable
Une valeur par défaut mutable est un objet par défaut stocké dont le contenu peut changer : les appels qui omettent l’argument peuvent donc partager les modifications précédentes.
Ajouter un élément à une liste de panier par défaut peut laisser cet élément visible lors de l’appel suivant.
Variable globale
Une variable globale appartient à la portée globale d’un fichier et peut être lue par les fonctions de ce fichier selon les règles de recherche des noms.
Un x = 10 au premier niveau reste à 10 lorsqu’une fonction auxiliaire affecte sa propre variable locale distincte x = 5.
Variable locale
Une variable locale appartient à un appel de fonction ; les paramètres et les noms ordinaires auxquels une valeur est affectée dans cette fonction sont des variables locales.
Chaque appel peut initialiser son propre count = 0, de sorte que deux appels peuvent afficher indépendamment la valeur 1.

À propos de cette unité

Par StudeliSignaler une erreur

Crée ton propre Matériel d'Étude

Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.

Commencer