3. Travail supplémentaire avec les fonctions

Appel d'une fonction et étude de la docstring

Quotient et reste (exercice_A33.py)

Nous avions défini la fonction division(). Elle est redonnée ci-dessous avec sa docstring (qui fait partie des éléments qu'il faudra savoir écrire dans une fonction). Vous devez la modifier de façon à ce qu'elle affiche le quotient et le reste de la division du nombre 100 par tous les nombres inférieurs ou égal à 50.


def division( n1, n2 ):
	"""
	Fonction pour calculer le quotient et le reste de la division de deux nombres.

	Pré :
		deux nombres n1, n2
	Post :
		deux entiers dans l'ordre : quotient, reste de la division de n1 par n2
	"""

	quotient = n1 // n2
	reste = n1 % n2
	return quotient, reste
			

Les résultats devront apparaître sous la forme suivante :


Le quotient de 100 par 1 est égal à 100, le reste à 0.
Le quotient de 100 par 2 est égal à 50, le reste à 0.
Le quotient de 100 par 3 est égal à 33, le reste à 1.
..................
Le quotient de 100 par 50 est égal à 2, le reste à 0.
		

Conversion décimal-binaire (exercice_A34.py)

Pour faire cet exercice, il faut d'abord avoir vu la partie B2 du cours sur les entiers relatifs et leur représentation en complément à deux. Si ce n'est pas le cas, sautez cet exercice et revenez y quand le cours aura été vu.

Compléter le script suivant de façon à ce qu'il utilise la fonction decToBin() pour afficher la conversion en binaire des entiers relatifs de -12710 à +12710.

Bien étudier auparavant la docstring de cette fonction !


def decToBin( dec ):
    """
    Fonction pour convertir un entier de la base 10 à la base 2 ( binaire ).
    La fonction ne peut convertir que les entiers positifs; 
    pour un nombre négatif, la conversion ne sera pas faite et le résultat retourné 
    sera du type 'None'.

    Pré-conditions :
        un nombre entier positif exprimé en base 10
    Post-conditions :
        une chaîne de caractère représentant la conversion en binaire de l'entier, avec les caractères '0b' en début de chaîne
        un booléen indiquant si la conversion a été faite ( True ) ou pas ( False )
    """

    if (dec < 0):
        return None , False

    q = dec
    b = ''
    while q != 0 :
        q = dec // 2
        r = dec % 2
        b = str(r) + b
        dec = q

    return '0b'+b , True
			

Construction et tests de fonctions

Travail à faire

Le but va être dans cette partie de réécrire quelques scripts "conventionnels" en les rendant "fonctionnels" ( au sens de "ils devront utiliser une fonction" ).

Dans chaque situation, vous réfléchirez aux spécifications de la fonction, vous la définirez complètement, vous écrirez sa docstring et vous la testerez.

Test d'une fonction : les tests unitaires

La notion de preuve et de tests est fondamentale en informatique : certains systèmes ne peuvent se contenter d'un fonctionnement approximatif mais doivent au contraire être robustes, c'est à dire fonctionner correctement dans toutes les situations possibles.

Pour prouver qu'une fonction fait toujours correctement le travail pour lequel elle est prévue, il faudrait théoriquement la tester avec tous les arguments possibles et imaginables; c'est bien entendu impossible...

On peut cependant se contenter de tester son bon fonctionnement sur quelques arguments bien choisis : on parle alors de tests unitaires

En Python, on peut utiliser le module doctest pour réaliser ces tests unitaires; il permet d'indiquer dans la docstring de la fonction des tests à réaliser et le résultat attendu si elle fonctionne bien.
Si ce n'est pas le cas, un message est alors affiché signalant qu'il faut corriger son code !

Voici un exemple avec la fonction division() :


import doctest

def division( n1, n2 ):
    """
    Fonction pour calculer le quotient et le reste de la division de deux nombres.

    Pré :
        deux nombres n1, n2
    Post :
        deux entiers dans l'ordre : quotient, reste de la division de n1 par n2

    Tests unitaires :
    >>> division(1,1)
    (1, 0)

    >>> division(2,1)
    (2, 0)

    >>> division(10,3)
    (3, 1)
    """

    quotient = n1 // n2
    reste = n1 % n2
    return quotient, reste

# Programme principal

doctest.testmod()	# exécution des test unitaires
			

Un test unitaire correspond aux 3 chevrons ( >>> ) suivis d'un espace puis de l'appel de la fonction avec des arguments particuliers; on indique en dessous le résultat attendu.

Si les tests unitaires sont validés, rien ne s'affiche. Par contre, en cas de mauvais fonctionnement, un ou plusieurs avertissement(s) s'affichent indiquant quel(s) test(s) n'ont pas été réussi(s).
Exemple avec la fonction précédente buguée :


import doctest

def division( n1, n2 ):
    """
    Fonction pour calculer le quotient et le reste de la division de deux nombres.

    Pré :
        deux nombres n1, n2
    Post :
        deux entiers dans l'ordre : quotient, reste de la division de n1 par n2

    Tests unitaires :
    >>> division(1,1)
    (1, 0)

    >>> division(2,1)
    (2, 0)

    >>> division(10,3)
    (3, 1)
    """

    quotient = n1 / n2  # LA FONCTION EST BUGUÉE !!!
    reste = n1 % n2
    return quotient, reste

# Programme principal

doctest.testmod()	# exécution des test unitaires
			

*********************************************************************
File "test.py", line 14, in __main__.division
Failed example:
    division(1,1)
Expected:
    (1, 0)
Got:
    (1.0, 0)
**********************************************************************
File "/home/chris/test.py", line 17, in __main__.division
Failed example:
    division(2,1)
Expected:
    (2, 0)
Got:
    (2.0, 0)
**********************************************************************
File "/home/chris/test.py", line 20, in __main__.division
Failed example:
    division(10,3)
Expected:
    (3, 1)
Got:
    (3.3333333333333335, 1)
**********************************************************************
1 items had failures:
   3 of   3 in __main__.division
***Test Failed*** 3 failures.

>>>
			

Une méthode de développement appelé TDD préconise d'ailleurs d'écrire D'ABORD des tests avant même le code d'une fonction...
Vous essayerez de procéder ainsi !

Conversion binaire-décimal (exercice_A35.py)

Le code ci-dessous permet la conversion d'un nombre en représentation binaire vers la base 10. Vous réécrirez ce script en y définissant une fonction binTodec() qui réalise la conversion.


binaire = input('Entrez le nombre binaire :')
decimal = 0
expo = len(binaire) - 1

for car in binaire:
    decimal += int(car)*(2**expo)
    expo -= 1

print("Valeur en base 10 :", decimal)
		

Rédigez correctement sa docstring après avoir analysé les entrées et les sorties nécessaires au bon fonctionnement de la fonction. Vous testerez le bon fonctionnement de la fonction avec des tests bien choisis !

Conversion de température (exercice_A36.py)

Le script ci-dessous permet de convertir une température de degrés Celsius en Fahrenheit ou l'inverse selon le choix de l'utilisateur :


t = float(input('Entrez la température à convertir :'))

n = int(input('Choisissez la conversion : 1. °C -> F     2. F -> °C '))

if n == 1 :
    print(32 + 1.8*t)

elif n == 2 :
    print((t - 32)/1.8)

else :
    print('Erreur !')
    	

Réécrire le script avec une unique fonction conv() qui retourne la conversion Celsius → Fahrenheit, ou Fahrenheit → Celsius.

Quel jour était-il ? (exercice_A37.py)

Ecrire et tester deux fonctions :


def est_bissextile( annee ) :
	..............
	..............
	return bool

def quel_jour( date ) :
	.............
	.............
	# appel de la fonction est_bissextile()
	.............
	.............
	return jour

# Programme principal
.....................
.....................
    	

Pensez à tester d'abord le bon fonctionnement de la première fonction avant de passer à la suite !