3. Fonctions▲
Dans le cadre de la programmation, une fonction est une séquence nommée d'instructions qui effectue un calcul. Lorsque vous définissez une fonction, vous spécifiez le nom et la séquence d'instructions. Plus tard, vous pouvez « appeler » la fonction par son nom.
3-1. Appels de fonctions▲
Nous avons vu déjà un exemple d'appel de fonction :
>>>
type(
42
)
<
class
'int'
>
Le nom de la fonction est type. L'expression entre parenthèses est appelée l'argument de la fonction. Le résultat, pour cette fonction, est le type de l'argument.
De façon usuelle, on dit que la fonction « prend » un argument et qu'elle « retourne » ou « renvoie » un résultat. Ce résultat est appelé aussi la valeur de retour.
Python fournit des fonctions qui convertissent des valeurs d'un type à l'autre. La fonction int prend n'importe quelle valeur et la convertit en un nombre entier, si elle le peut, ou se plaint dans le cas contraire :
La fonction int peut convertir les valeurs à virgule flottante en entiers, mais elle n'arrondit pas ; elle en coupe la partie fractionnaire :
La fonction float convertit des entiers et des chaînes de caractères en nombres à virgule flottante :
Enfin, str convertit son argument en une chaîne :
3-2. Fonctions mathématiques▲
Python dispose d'un module math, qui fournit la plupart des fonctions mathématiques usuelles. Un module est un fichier qui contient une collection de fonctions apparentées.
Avant que nous puissions utiliser les fonctions d'un module, nous devons l'importer avec une instruction import :
>>>
import
math
Cette instruction crée un objet module nommé math. Si vous affichez l'objet module, vous obtiendrez quelques informations à son sujet :
>>>
math
<
module 'math'
(
built-
in
)>
L'objet module contient les fonctions et variables définies dans le module. Pour accéder à l'une des fonctions, vous devez spécifier le nom du module et le nom de la fonction, séparés par un point. Ce format est appelé notation pointée ou parfois notation objet.
>>>
ratio =
puissance_signal /
puissance_bruit
>>>
decibels =
10
*
math.log10
(
ratio)
>>>
radians =
0.7
>>>
hauteur =
math.sin
(
radians)
Le premier exemple utilise math.log10 pour calculer un rapport signal / bruit en décibels (en supposant que force_signal et force_bruit sont définis). Le module math fournit également log, qui calcule des logarithmes en base e.
Le second exemple trouve le sinus de radians. Le nom de la variable est une indication que sin et les autres fonctions trigonométriques (cos, tan, etc.) prennent des arguments mesurés en radians. Pour convertir de degrés en radians, divisez par 180 et multipliez par π :
>>>
degrees =
45
>>>
radians =
degrees /
180.0
*
math.pi
>>>
math.sin
(
radians)
0.707106781187
L'expression math.pi obtient la variable pi à partir du module math. Sa valeur est une approximation à virgule flottante de π, avec une précision d'environ 15 chiffres.
Si vous avez des notions de trigonométrie, vous pouvez vérifier le résultat précédent en le comparant à la racine carrée de deux divisée par deux :
>>>
math.sqrt
(
2
) /
2.0
0.707106781187
3-3. Composition▲
Jusqu'ici, nous avons examiné les éléments d'un programme - variables, expressions et instructions - en les traitant de façon isolée, sans parler de la façon de les combiner.
L'une des caractéristiques les plus utiles des langages de programmation est leur capacité de prendre de petites briques de construction et de les composer. Par exemple, l'argument d'une fonction peut être tout type d'expression, y compris une expression comprenant des opérateurs arithmétiques :
x =
math.sin
(
degres /
360.0
*
2
*
math.pi)
et même des appels de fonction :
x =
math.exp
(
math.log
(
x+
1
))
Presque partout où vous pouvez mettre une valeur, vous pouvez mettre une expression arbitraire, à une exception près : le côté gauche d'une instruction d'affectation doit être un nom de variable. Toute autre expression sur le côté gauche est une erreur de syntaxe (nous verrons plus tard des exceptions à cette règle).
>>>
minutes =
heures *
60
# correct
>>>
heures *
60
=
minutes # incorrect !
SyntaxError
: can't assign to operator
3-4. Créer de nouvelles fonctions▲
Jusqu'à présent, nous n'avons utilisé que des fonctions fournies par Python, mais il est également possible d'ajouter de nouvelles fonctions. Une définition de fonction spécifie le nom d'une nouvelle fonction et la séquence d'instructions exécutées lorsque la fonction est appelée.
Voici un exemple :
def
afficher_paroles
(
):
print
(
"J'abats des arbres, je danse et saute,"
)
print
(
"J'aime jouer avec des pâquerettes."
)
Le mot clé def indique qu'il s'agit d'une définition de fonction. Le nom de la fonction est afficher_paroles. Les règles pour les noms de fonction sont les mêmes que pour les noms de variables : des lettres, des chiffres et des traits de soulignement sont autorisés, mais le premier caractère ne peut pas être un chiffre. Vous ne pouvez pas utiliser un mot-clé comme nom d'une fonction, et vous devriez éviter d'avoir une variable et une fonction du même nom.
Les parenthèses vides après le nom indiquent que cette fonction ne prend aucun argument.
La première ligne de la définition de la fonction est appelée l'en-tête ; le reste est appelé le corps. L'en-tête doit se terminer par un deux-points et le corps doit être indenté (les lignes commencent par des espaces). Par convention, l'indentation est toujours de quatre espaces. Le corps peut contenir un nombre quelconque d'instructions. La fin de l'indentation (retour au début de la ligne) marque la fin de la définition de la fonction.
Les chaînes dans les instructions d'impression sont entre guillemets doubles. Les guillemets simples et doubles font la même chose ; la plupart des gens utilisent des guillemets simples, sauf dans des cas comme celui-ci, où un guillemet simple (qui est aussi une apostrophe) apparaît dans la chaîne.
Tous les guillemets (simples et doubles) doivent être des « guillemets droits ». Les guillemets français ne sont pas autorisés en Python.
Si vous tapez une définition de fonction en mode interactif, l'interpréteur affiche trois points (...) pour vous faire savoir que la définition est incomplète :
>>>
def
afficher_paroles
(
):
... print
(
"J'abats des arbres, je danse et saute,"
)
... print
(
"J'aime jouer avec des pâquerettes."
)
...
Pour mettre fin à la fonction, vous devez entrer une ligne vide.
Définir une fonction crée un objet fonction, de type function :
>>>
print
(
afficher_paroles)
<
function afficher_paroles at 0xb7e99e9c
>
>>>
type(
afficher_paroles)
<
class
'function'
>
La syntaxe pour appeler la nouvelle fonction est la même que pour les fonctions internes :
>>>
afficher_paroles
(
)
J'abats des arbres, je danse et saute,
J'
aime jouer avec des pâquerettes.
Une fois que vous avez défini une fonction, vous pouvez l'utiliser dans une autre fonction. Par exemple, pour répéter le refrain précédent, nous pourrions écrire une fonction appelée repeter_paroles :
def
repeter_paroles
(
):
afficher_paroles
(
)
afficher_paroles
(
)
Puis appeler repeter_paroles :
>>>
repeter_paroles
(
)
J'abats des arbres, je danse et saute,
J'
aime jouer avec des pâquerettes.
J'abats des arbres, je danse et saute,
J'
aime jouer avec des pâquerettes.
Mais cela ne respecte plus vraiment les paroles de la chanson des Monty Python.
3-5. Définitions et utilisation▲
En rassemblant les fragments de code de la section précédente, le programme complet ressemble à ceci :
def
afficher_paroles
(
):
print
(
"J'abats des arbres, je danse et saute,"
)
print
(
"J'aime jouer avec des pâquerettes."
)
def
repeter_paroles
(
):
afficher_paroles
(
)
afficher_paroles
(
)
repeter_paroles
(
)
Ce programme contient deux définitions de fonctions : afficher_paroles et repeter_paroles. Les définitions de fonctions sont exécutées exactement comme les autres instructions, mais l'effet est de créer des objets fonction. Les instructions à l'intérieur de la fonction ne sont pas exécutées jusqu'à ce que la fonction soit appelée, et la définition de la fonction ne génère aucune sortie.
Comme vous vous y attendez, vous devez créer une fonction avant de pouvoir l'exécuter. Autrement dit, la définition de la fonction doit être exécutée avant que la fonction soit appelée.
Comme exercice, déplacez la dernière ligne de ce programme au début, de sorte que l'appel de fonction apparaisse avant les définitions. Exécutez le programme et voyez quel message d'erreur vous obtenez.
Maintenant, remettez l'appel de la fonction en bas et déplacez la définition de afficher_paroles après la définition de repeter_paroles. Qu'advient-il lorsque vous exécutez ce programme ?
3-6. Flux d'exécution▲
Pour garantir qu'une fonction soit définie avant sa première utilisation, vous devez connaître l'ordre dans lequel les instructions sont exécutées ; c'est ce que l'on appelle le flux d'exécution.
L'exécution commence toujours à la première instruction du programme. Les instructions sont exécutées une par une, dans l'ordre de haut en bas.
Les définitions de fonctions ne modifient pas le flux d'exécution du programme, mais rappelez-vous que les instructions à l'intérieur de la fonction ne sont pas exécutées avant que la fonction soit appelée.
Un appel de fonction est comme un détour dans le flux d'exécution. Au lieu d'aller à l'instruction suivante, le flux saute dans le corps de la fonction, il en exécute les instructions, puis il revient et reprend là où il s'était interrompu.
Cela semble assez simple, mais souvenez-vous qu'une fonction peut appeler une autre fonction. Lorsqu'il est arrivé au milieu d'une fonction, le programme peut devoir exécuter les instructions d'une autre fonction. Puis, lors de l'exécution de cette nouvelle fonction, le programme pourrait avoir à exécuter une autre fonction !
Heureusement, Python est doué pour garder la trace de l'endroit où il était arrivé, de sorte que chaque fois qu'une fonction se termine, le programme reprend là où il en était dans la fonction qui l'a appelée. Quand il arrive à la fin du programme, il se termine.
En résumé, lorsque vous lisez un programme, vous ne voulez pas toujours lire le code de haut en bas. Parfois, il est plus judicieux de suivre le flux d'exécution.
3-7. Paramètres et arguments▲
Certaines des fonctions que nous avons vues exigent des arguments. Par exemple, lorsque vous appelez math.sin vous passez un nombre comme un argument. Certaines fonctions prennent plus d'un argument : math.pow en prend deux, la base et l'exposant.
Dans la fonction, les arguments sont assignés à des variables appelées paramètres. Voici une définition pour une fonction qui prend un argument :
def
afficher_deux_fois
(
bruce):
print
(
bruce)
print
(
bruce)
Cette fonction assigne l'argument à un paramètre nommé bruce. Lorsque la fonction est appelée, elle affiche la valeur du paramètre (quel qu'il soit) à deux reprises.
Cette fonction marche pour n'importe quelle valeur qui peut être affichée.
>>>
afficher_deux_fois
(
'Spam'
)
Spam
Spam
>>>
afficher_deux_fois
(
42
)
42
42
>>>
afficher_deux_fois
(
math.pi)
3.14159265359
3.14159265359
Les règles de composition applicables aux fonctions internes s'appliquent également aux fonctions définies par le programmeur, donc nous pouvons utiliser tout type d'expression comme argument pour afficher_deux_fois :
>>>
afficher_deux_fois
(
'Spam '
*
4
)
Spam Spam Spam Spam
Spam Spam Spam Spam
>>>
afficher_deux_fois
(
math.cos
(
math.pi))
-
1.0
-
1.0
L'argument est évalué avant que la fonction soit appelée, donc dans les exemples précédents, les expressions 'Spam ' * 4 et math.cos(math.pi) sont évaluées une seule fois.
Vous pouvez également utiliser une variable comme argument :
>>>
michael =
'Eric, le demi-abeille.'
>>>
afficher_deux_fois
(
michael)
Eric, le demi-
abeille.
Eric, le demi-
abeille.
Le nom de la variable que nous passons comme argument (michael) n'a rien à voir avec le nom du paramètre (bruce). Peu importe comment s'appelait la valeur chez elle (dans la fonction appelante) ; ici, dans afficher_deux_fois, nous appelons tout le monde bruce.
3-8. Les variables et les paramètres sont locaux▲
Lorsque vous créez une variable dans une fonction, elle est locale à cette fonction, ce qui signifie qu'elle existe seulement à l'intérieur de la fonction. Par exemple :
def
concat_deux_fois
(
partie1, partie2):
concat =
partie1 +
partie2
afficher_deux_fois
(
concat)
Cette fonction prend deux arguments, les concatène et affiche le résultat deux fois. Voici un exemple qui l'utilise :
>>>
ligne1 =
'Bing tiddle '
>>>
ligne2 =
'tiddle bang.'
>>>
concat_deux_fois
(
ligne1, ligne2)
Bing tiddle tiddle bang.
Bing tiddle tiddle bang.
Lorsque concat_deux_fois se termine, la variable concat est détruite. Si nous essayons de l'afficher, nous obtenons une exception :
>>>
print
(
concat)
NameError
: name 'concat'
is
not
defined
Les paramètres aussi sont locaux. Par exemple, en dehors de concat_deux_fois, il n'existe rien qui s'appelle bruce.
3-9. Diagrammes de pile▲
Pour garder une trace des variables pouvant être utilisées à tel ou tel endroit, il est parfois utile de dessiner un diagramme de pile d'exécution. Comme les diagrammes d'états, les diagrammes de pile montrent la valeur de chaque variable, mais ils montrent également la fonction à laquelle appartient chaque variable.
Chaque fonction est représentée par une structure de pile. Une structure de pile est une boîte ayant à côté d'elle un nom de fonction et, à l'intérieur, les paramètres et les variables de la fonction. Le schéma de pile pour l'exemple précédent est illustré sur la figure 3.1.
Ces structures sont disposées en une pile qui indique quelle fonction a appelé quelle fonction, et ainsi de suite. Dans cet exemple, afficher_deux_fois a été appelée par concat_deux_fois et cette dernière a été appelée par __main__, qui est un nom spécial pour la structure située au sommet de la pile. Lorsque vous créez une variable en dehors de toute fonction, elle appartient à __main__.
Chaque paramètre se réfère à la même valeur que son argument correspondant. Donc, partie1 a la même valeur que ligne1, partie2 a la même valeur que ligne2, et bruce a la même valeur que concat.
Si une erreur se produit lors d'un appel de fonction, Python affiche le nom de la fonction en question, le nom de la fonction appelante, et ainsi de suite, jusqu'à __main__.
Par exemple, si vous essayez d'accéder à concat à l'intérieur de afficher_deux_fois, vous obtenez une NameError :
Traceback (
innermost last):
File "test.py"
, line 13
, in
__main__
concat_deux_fois
(
ligne1, ligne2)
File "test.py"
, line 5
, in
concat_deux_fois
afficher_deux_fois
(
concat)
File "test.py"
, line 9
, in
afficher_deux_fois
print
(
concat)
NameError
: name 'concat'
is
not
defined
Cette liste de fonctions s'appelle une trace d'appel. Elle vous indique dans quel fichier du programme se trouve l'erreur, et à quelle ligne, et quelles fonctions étaient en cours d'exécution au moment où l'erreur est survenue. Elle montre également la ligne de code qui a provoqué l'erreur.
L'ordre des fonctions dans la trace d'appel est le même que l'ordre des structures de pile dans le schéma de la pile. La fonction en cours d'exécution est en bas.
3-10. Fonctions productives et fonctions vides▲
Certaines des fonctions que nous avons utilisées, telles que les fonctions du module math, produisent des résultats ; faute d'un meilleur terme, je les appelle fonctions productives. D'autres fonctions, comme afficher_deux_fois, effectuent une action, mais ne retournent aucune valeur. On les appelle des fonctions vides (void, en anglais).
Lorsque vous appelez une fonction productive, vous voulez presque toujours en exploiter le résultat ; par exemple, vous pouvez l'assigner à une variable ou l'utiliser dans le cadre d'une expression :
x =
math.cos
(
radians)
nombre_d_or =
(
math.sqrt
(
5
) +
1
) /
2
Lorsque vous appelez une fonction en mode interactif, Python affiche le résultat :
>>>
math.sqrt
(
5
)
2.2360679774997898
Mais dans un script, si vous ne faites qu'appeler une fonction productive, la valeur de retour est perdue à jamais !
math.sqrt
(
5
)
Ce script calcule la racine carrée de 5, mais comme il ne stocke ni n'affiche le résultat, il n'est pas très utile.
Les fonctions void peuvent par exemple afficher quelque chose sur l'écran ou avoir un autre effet, mais elles n'ont aucune valeur de retour. Si vous affectez leur résultat à une variable, vous obtenez une valeur spéciale appelée None.
>>>
resultat =
afficher_deux_fois
(
'Bing'
)
Bing
Bing
>>>
print
(
resultat)
None
La valeur None n'est pas la même chose que la chaîne 'None'. C'est une valeur spéciale, qui a son propre type :
>>>
print
(
type(
None
))
<
class
'NoneType'
>
Les fonctions que nous avons écrites jusqu'à présent sont toutes vides. Nous allons commencer à écrire des fonctions productives d'ici quelques chapitres.
3-11. Pourquoi des fonctions ?▲
Les motifs pour lesquels on prend la peine de diviser un programme en fonctions ne sont peut-être pas très clairs. Il existe plusieurs raisons à cela :
- la création d'une nouvelle fonction vous donne la possibilité de nommer un groupe d'instructions, ce qui rend votre programme plus facile à lire et à déboguer ;
- les fonctions peuvent réduire la taille d'un programme en éliminant les répétitions de code. Plus tard, si vous faites une modification, vous aurez à le faire à un seul endroit ;
- diviser un programme long en fonctions vous permet de déboguer les parties une par une, puis de les rassembler en un tout qui fonctionne ;
- les fonctions bien conçues sont souvent utiles pour de nombreux programmes. Une fois que vous en écrivez et déboguez une, vous pouvez la réutiliser.
3-12. Débogage▲
L'une des compétences les plus importantes que vous acquerrez est le débogage. Bien qu'il puisse être frustrant, le débogage est une des parties les plus intellectuellement riches, stimulantes et intéressantes de la programmation.
À certains égards, le débogage est comme un travail de détective. Vous vous trouvez en présence d'indices et vous devez déduire les processus et les événements qui ont conduit aux résultats que vous voyez.
Le débogage est aussi une forme de science expérimentale. Une fois que vous avez une idée sur ce qui va mal, vous modifiez votre programme et essayez à nouveau. Si votre hypothèse est correcte, vous pouvez prédire le résultat de la modification et vous faites un pas de plus vers un programme fonctionnel. Si votre hypothèse est fausse, vous devez en formuler une autre. Comme Sherlock Holmes l'a souligné, « Lorsque vous avez éliminé l'impossible, ce qui reste, si improbable soit-il, est nécessairement la vérité. » (A. Conan Doyle, Le signe des Quatre)
Pour certaines personnes, la programmation et le débogage sont la même chose. Autrement dit, la programmation est le processus de débogage progressif d'un programme jusqu'à ce qu'il fasse ce que vous voulez. L'idée est que vous devriez commencer avec un programme fonctionnel et lui apporter de petites modifications, en les déboguant au fur et à mesure.
Par exemple, Linux est un système d'exploitation qui contient des millions de lignes de code, mais il a commencé par être un simple programme que Linus Torvalds a utilisé pour explorer la puce Intel 80386. Selon Larry Greenfield, « Un des projets antérieurs de Linus était un programme qui permettrait de basculer entre l'affichage de AAAA et BBBB. Cela a évolué plus tard vers Linux. » (Le guide des utilisateurs Linux Version 1 Bêta).
3-13. Glossaire▲
- fonction : une séquence nommée d'instructions qui effectue une opération utile. Les fonctions peuvent prendre des arguments ou pas et peuvent produire un résultat ou pas.
- définition de fonction : une instruction qui crée une nouvelle fonction, en spécifiant son nom, les paramètres et les instructions qu'elle contient.
- objet fonction : une valeur créée par une définition de fonction. Le nom de la fonction est une variable qui fait référence à un objet fonction.
- en-tête : la première ligne de la définition de fonction.
- corps : la séquence d'instructions à l'intérieur de la définition de la fonction.
- paramètre : un nom utilisé à l'intérieur d'une fonction pour faire référence à la valeur passée en argument.
- appel de fonction : une instruction qui exécute la fonction. Elle se compose du nom de la fonction suivi par une liste éventuelle d'arguments entre parenthèses.
- argument : une valeur fournie à une fonction lorsque la fonction est appelée. Cette valeur est affectée au paramètre correspondant à l'intérieur de la fonction.
- variable locale : une variable définie à l'intérieur d'une fonction. Une variable locale peut être utilisée uniquement à l'intérieur de la fonction où elle a été définie.
- valeur de retour : le résultat retourné par une fonction. Si un appel de fonction est utilisé comme une expression, alors cette expression prend pour valeur la valeur retournée par la fonction.
- fonction productive : une fonction qui retourne une valeur.
- fonction vide : une fonction qui retourne toujours la valeur None.
- None : une valeur spéciale retournée par les fonctions vides.
- module : un fichier qui contient une collection de fonctions apparentées et d'autres définitions.
- instruction d'importation : une instruction qui lit un fichier de module et crée un objet module.
- objet module : une valeur créée par une instruction import, qui permet d'accéder aux valeurs définies dans un module.
- notation pointée : la syntaxe permettant d'appeler une fonction définie dans un module, en spécifiant le nom du module suivi par un point et le nom de la fonction.
- composition : l'utilisation d'une expression comme partie d'une expression plus grande, ou d'une instruction dans le cadre d'une instruction plus complexe.
- flux d'exécution : l'ordre dans lequel les commandes sont exécutées.
- diagramme de pile : une représentation graphique d'un empilement de fonctions, leurs variables et les valeurs qu'elles réfèrent.
- structure de pile : une boîte dans un diagramme de pile qui représente un appel de fonction. Elle contient les variables locales et les paramètres de la fonction.
- trace d'appel : une liste des fonctions en cours d'exécution, affichée lorsqu'une exception se produit.
3-14. Exercices▲
Exercice 1
Écrivez une fonction nommée aligner_a_droite qui prend comme paramètre une chaîne nommée s et affiche cette chaîne avec suffisamment de caractères espace pour que la dernière lettre de la chaîne se trouve dans la colonne 70 de l'écran.
>>>
aligner_a_droite
(
'monty'
)
monty
Indice : utilisez les opérateurs de concaténation et de répétition de chaînes. Notez aussi que Python fournit une fonction interne appelée len , qui renvoie la longueur d'une chaîne, de sorte que la valeur de len('monty') est 5.
Exercice 2
Un objet fonction est une valeur que vous pouvez assigner à une variable ou transmettre en tant qu'argument. Par exemple, appeler_deux_fois est une fonction qui prend comme argument un objet fonction et l'appelle deux fois :
def
appeler_deux_fois
(
f):
f
(
)
f
(
)
Voici un exemple qui utilise appeler_deux_fois pour appeler deux fois une fonction nommée afficher_spam .
def
print_spam
(
):
print
(
'spam'
)
appeler_deux_fois
(
print_spam)
- Tapez cet exemple dans un script et testez-le.
- Modifiez la fonction appeler_deux_fois de sorte qu'elle prenne deux arguments, un objet fonction et une valeur, et appelle la fonction à deux reprises, en passant la valeur comme argument.
- Copiez la définition de la fonction afficher_deux_fois utilisée plus tôt dans ce chapitre dans votre script.
- Utilisez la version modifiée de la fonction appeler_deux_fois pour appeler à deux reprises la fonction afficher_deux_fois deux fois, en passant 'spam' comme argument.
- Définissez une nouvelle fonction appelée appeler_quatre_fois , qui prend un objet fonction et une valeur et appelle la fonction quatre fois, en passant la valeur comme paramètre. Il ne devrait y avoir que deux instructions dans le corps de cette fonction, et non quatre.
Solution : do_four.py.
Exercice 3
Note : cet exercice devrait être fait en n'utilisant que les instructions et les autres fonctionnalités que nous avons apprises jusqu'ici.
-
Écrire une fonction qui affiche une grille comme ce qui suit :
Sélectionnez+
-
-
-
-
+
-
-
-
-
+
|
|
|
|
|
|
|
|
|
|
|
|
+
-
-
-
-
+
-
-
-
-
+
|
|
|
|
|
|
|
|
|
|
|
|
+
-
-
-
-
+
-
-
-
-
+
Indice : pour imprimer plus d'une valeur sur une ligne, vous pouvez imprimer une séquence de valeurs séparées par des virgules :
Sélectionnezprint
(
'+'
,'-'
)Par défaut, print passe à la ligne suivante, mais vous pouvez modifier ce comportement et mettre un espace à la fin, comme ceci :
Sélectionnezprint
(
'+'
, end=
' '
)print
(
'-'
)Ces instructions affichent '+ -'.
Une instruction print sans aucun argument termine la ligne courante et va à la ligne suivante. - Écrivez une fonction qui affiche une grille similaire avec quatre lignes et quatre colonnes.
Solution : grid.py. Référence : cet exercice est basé sur un exercice de Oualline, Programmation pratique en C, troisième édition, O'Reilly Media 1997.