Parcours
/
Python
Python
/
Exercices
/
Les sublimes lasagnes de Guido
Les sublimes lasagnes de Guido

Les sublimes lasagnes de Guido

Exercice d'apprentissage

Introduction

Python est un langage de programmation à typage dynamique et fort. Il utilise à la fois le duck typing et le typage progressif via les annotations de type.

Bien que Python prenne en charge de nombreux styles de programmation, en interne tout, en Python, est un objet. Cela inclut les nombres, les strings, les tableaux et même les fonctions.

On verra plus en détail ce que tout cela signifie au fil du parcours.

Ce premier exercice présente 4 caractéristiques majeures du langage Python :

  1. L'affectation de noms (variables et constantes),
  2. Les fonctions (le mot-clé def et le mot-clé return),
  3. Les commentaires, et
  4. Les docstrings.

Note

De manière générale, le contenu, les tests et l'outillage d'analyse du parcours Python suivent les conventions de style décrites dans PEP 8 et PEP 257 pour le style de code Python, avec la suggestion supplémentaire (forte) de ne pas utiliser de noms de variables d'une seule lettre ni de variables nommées « _ ».

Dans le parcours Python, les variables s'écrivent toujours en snake_case, et les constantes en SCREAMING_SNAKE_CASE.


Affectation de noms (variables et constantes)

Les développeurs peuvent lier des noms (aussi appelés variables) à n'importe quel type d'objet avec l'opérateur d'affectation = : <name> = <value>. Un nom peut être réaffecté (ou relié à nouveau) à d'autres valeurs (d'autres types d'objets) au cours de sa vie.

>>> my_first_variable = 1  #<-- my_first_variable bound to an integer object of value one.
>>> my_first_variable = 2  #<-- my_first_variable re-assigned to integer value 2.

>>> print(type(my_first_variable))
<class 'int'>

>>> print(my_first_variable)
2

>>> my_first_variable = "Now, I'm a string." #<-- You may re-bind a name to a different object type and value.
>>> print(type(my_first_variable))
<class 'str'>

>>> my_first_variable = 'You can call me "str".' #<-- Strings can be declared using single or double quote marks.
>>> print(my_first_variable)
You can call me "str".

Constantes

Les constantes sont des noms censés n'être affectés qu'une seule fois dans un programme. Elles doivent être définies au niveau d'un module (fichier), et sont généralement visibles par toutes les fonctions et classes du programme. Utiliser SCREAMING_SNAKE_CASE signale que le nom ne doit pas être réaffecté, ni sa valeur modifiée.

Fonctions

Le mot-clé def commence une définition de fonction. Chaque fonction peut prendre zéro ou plusieurs paramètres formels entre parenthèses (), suivis de deux-points :. Les instructions qui forment le corps de la fonction commencent sur la ligne qui suit def et doivent être indentées en bloc.

# The body of a function is indented by 2 spaces, & prints the sum of the numbers.
def add_two_numbers(number_one, number_two):
  total = number_one + number_two
  print(total)  

>>> add_two_numbers(3, 4)
7


# Inconsistent indentation in your code blocks will raise an error.
>>> def add_three_numbers_misformatted(number_one, number_two, number_three):
...     result = number_one + number_two + number_three   # This was indented by 4 spaces.
...    print(result)     #this was only indented by 3 spaces
...
...
  File "<stdin>", line 3
    print(result)
    ^
IndentationError: unindent does not match any outer indentation level

Les fonctions renvoient explicitement une valeur ou un objet grâce au mot-clé return :

# Function definition on first line, explicit return used on final line.
>>> def add_two_numbers(number_one, number_two):
        return number_one + number_two   


# Calling the function in the Python shell returns the sum of the numbers.
>>> add_two_numbers(3, 4)
7

# Assigning the function call to a variable and printing it 
# will also return the value.
>>> sum_with_return = add_two_numbers(5, 6)
>>> print(sum_with_return)
11

Les fonctions qui n'ont pas d'expression explicite après un return renvoient implicitement l'objet None. Les détails de None seront abordés dans un exercice ultérieur. Pour les besoins de cet exercice et de cette explication, None est une valeur de remplacement qui ne représente rien, autrement dit null :


# This function will return `None`
def square_a_number(number):
    square = number * number
    return # <-- note that this return is not followed by an expression

# Calling the function in the Python shell appears 
# to not return anything at all.
>>> square_a_number(2)
>>>


# Using print() with the function call shows that 
# the function is actually returning the **None** object.
>>> print(square_a_number(2))
None

Les fonctions qui omettent return renvoient elles aussi implicitement l'objet None. Cela signifie que si tu n'utilises pas return dans une fonction, Python renverra l'objet None pour toi.

# This function omits a return keyword altogether.
def add_two_numbers(number_one, number_two):
  result = number_one + number_two

>>> add_two_numbers(5, 7)
>>> print(add_two_numbers(5, 7))
None

# Assigning the function call to a variable and printing 
# the variable will also show None.
>>> sum_without_return = add_two_numbers(5, 6)
>>> print(sum_without_return)
None

Appelle des fonctions

On appelle les fonctions (on les invoque) en écrivant leur nom suivi de (). La notation pointée (.) sert à appeler des fonctions définies à l'intérieur d'une classe ou d'un module.

>>> def raise_to_power(number, power):
...     return number ** power
...

>>> raise_to_power(3,3) # <--Invoking the function with the arguments 3 and 3.
27


# A mismatch between the number of parameters and the number of arguments will raise an error.
>>> raise_to_power(4,)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: raise_to_power() missing 1 required positional argument: 'power'


# Calling methods or functions in classes and modules.
>>> start_text = "my silly sentence for examples."
>>> str.upper(start_text)  # <--Calling the upper() method from the built-in str class on start_text.
'MY SILLY SENTENCE FOR EXAMPLES.'


# Importing the math module
>>> import math

>>> math.pow(2,4)  # <--Calling the pow() function from the math module.
16.0

Commentaires

En Python, les commentaires commencent par un # qui ne fait pas partie d'une string, et se terminent à la fin de la ligne. Contrairement à de nombreux autres langages de programmation, Python ne prend pas en charge les marques de commentaire sur plusieurs lignes. Chaque ligne d'un bloc de commentaire doit commencer par le caractère #.

Docstrings

La première instruction du corps d'une fonction peut éventuellement être une docstring, qui résume de façon concise l'objectif de la fonction ou de l'objet. Les docstrings sont déclarées à l'aide de triples guillemets doubles (""") indentés au même niveau que le bloc de code :


# An example from PEP257 of a multi-line docstring
# reformatted to use Google style non-type hinted docstrings.
# Some additional details can be found in the Sphinx documentation:
# https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html#getting-started

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    Keyword Arguments:
        real (float): The real part of the number (default 0.0)
        imag (float): The imaginary part of the number (default 0.0)
        
    """

    if imag == 0.0 and real == 0.0:
        return complex_zero

Les docstrings sont lues par des outils de documentation automatisée comme Sphinx et sont renvoyées en appelant l'attribut spécial .__doc__ sur le nom de la fonction, de la méthode ou de la classe. Les conventions générales des docstrings sont décrites dans la PEP257, mais les formats exacts varient selon le projet et l'équipe. Les exercices d'apprentissage d'Exercism essaient de suivre le style Google pour le code sans annotations de type.

Les docstrings peuvent aussi servir de tests unitaires légers, ce qui sera abordé dans un exercice ultérieur.

# An example on a user-defined function using a Google style docstring. 
>>> def raise_to_power(number, power):
    """Raise a number to an arbitrary power.

    Parameters:
        number (int): The base number.
        power (int): The power to raise the base number to.
    
    Returns:
        int: The number raised to the specified power.
    
    Takes a number and raises it to the specified power, returning the result.

    """

    return number ** power
...

# Calling the .__doc__ attribute of the function and printing the result.
>>> print(raise_to_power.__doc__)
Raise a number to an arbitrary power.

Parameters:
    number (int): The base number.
    power (int): The power to raise the base number to.

Returns:
    int: The number raised to the specified power.

Takes a number and raises it to the specified power, returning the result.

Instructions

Tu vas écrire du code pour t'aider à cuisiner une magnifique lasagne tirée de ton livre de recettes préféré.

Tu as cinq tâches, toutes liées à la préparation de ta recette.


Note

Nous avons déjà commencé la première définition de fonction à ta place dans le fichier stub, mais tu devras écrire toi-même les définitions de fonctions restantes. Tu devras aussi définir toi-même les constantes dont tu as besoin. Lis attentivement les lignes de commentaire #TODO dans le fichier stub. Une fois une tâche terminée, supprime le commentaire TODO.


1. Définis le temps de cuisson attendu en minutes sous forme de constante

Définis la constante EXPECTED_BAKE_TIME qui représente le nombre de minutes pendant lesquelles la lasagne doit cuire au four. D'après ton livre de recettes, la lasagne doit rester au four pendant 40 minutes :

>>> print(EXPECTED_BAKE_TIME)
40

2. Calcule le temps de cuisson restant en minutes

Complète la fonction bake_time_remaining() qui prend en argument le nombre de minutes que la lasagne a déjà passées au four et renvoie le nombre de minutes de cuisson dont la lasagne a encore besoin, d'après la constante EXPECTED_BAKE_TIME.

>>> bake_time_remaining(30)
10

3. Calcule le temps de préparation en minutes

Définis la fonction preparation_time_in_minutes() qui prend en argument le number_of_layers que tu veux ajouter à la lasagne et renvoie le nombre de minutes que tu passerais à les préparer. On considère que chaque couche demande 2 minutes de préparation.

>>> def preparation_time_in_minutes(number_of_layers):
        ...
        ...
        
>>> preparation_time_in_minutes(2)
4

4. Calcule le temps total écoulé (préparation + cuisson) en minutes

Définis la fonction elapsed_time_in_minutes() qui prend deux paramètres en arguments :

  • number_of_layers (le nombre de couches ajoutées à la lasagne)
  • elapsed_bake_time (le nombre de minutes que la lasagne a déjà passées au four).

Cette fonction doit renvoyer le nombre total de minutes que tu as passées en cuisine : ton temps de préparation des couches + le temps que la lasagne a passé au four.

>>> def elapsed_time_in_minutes(number_of_layers, elapsed_bake_time):
        ...
        ...
        
>>> elapsed_time_in_minutes(3, 20)
26

5. Mets à jour la recette avec des notes

Reprends la recette et ajoute des « notes » sous la forme de docstrings de fonction.

def elapsed_time_in_minutes(number_of_layers, elapsed_bake_time):
    """Calculate the elapsed cooking time.
    
    Parameters:
        number_of_layers (int): The number of layers in the lasagna.
        elapsed_bake_time (int): Time the lasagna has been baking in the oven.
    
    Returns:
        int: The total time elapsed (in minutes) preparing and baking.

    This function takes two integers representing the number of lasagna 
    layers and the time already spent baking the lasagna. It calculates 
    the total elapsed minutes spent cooking (preparing + baking).
    
    """
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Python Exercism

Prêt à commencer Les sublimes lasagnes de Guido ?

Inscris-toi sur Exercism pour apprendre et maîtriser Python avec 17 concepts146 exercices, et un vrai mentorat humain, le tout gratuitement.