42 - Programme en tant que donneé
Nous allons voir aujourd'hui qu'un programme n'est qu'une donnée comme une autre (vous avez déjà vu).
Nous allons d'ailleurs aujourd'hui créer notre propre interpréteur !
Logiciel nécessaire pour l'activité : Python 3 : Thonny, IDLE ...
Résumé :
1 - Programme en tant que donnée : la théorie
Pour comprendre ce que nous allons faire aujourd'hui, il est important de comprendre qu'un programme n'est au final :
- qu'une suite de caractères dans le cas d'un code-source
- qu'une suite d'octet (ou de bits) dans le cas d'un code-binaire
Et encore : comme on encode les caractères comme des suites d'octets, on obtient uniquement des bits dans les deux cas.
Qui dit donnée, dit programme ou fonction capable de les traiter.
Vous avez déjà vu de nombreux exemples de programmes capables de faire cela :
- Le compilateur C
- L'interpréteur Python
- La création d'un processus
- Le téléchargement d'un programme
On lui fournit un code-source en entrée et le transforme en code binaire.
Le prototype de la fonction équivalente imagée serait :
1 |
|
On lui fournit un code-source en entrée et le transforme à la volée en un code binaire (ou un code compréhensible pour un autre programme qui pourra le faire.
Le prototype de la fonction équivalente imagée serait :
1 |
|
D'ailleurs, vous lancez souvent vos scripts Python depuis Thonny mais vous pourriez faire la même chose en utilisant directement un appel à Python. Imaginons que la console ci-dessous pointe actuellemnet dans le répertoire contenant un code-source Python nommé directement.py. Pour lancer son exécution, il suffit de taper cela :
alias@mon_ordi:~$ cd Documents/prog_python/
alias@mon_ordi:~/Documents/prog_python$ python3 dichotomie.py
On fournit le PID du processus parent (PPID donc) et le code binaire d'un programme au système d'exploitation qui va le transformer en processus et va fournir l'identifiant PID permettant de le gérer.
Le prototype de la fonction équivalente imagée serait :
1 |
|
Que se passe-t-il lorsque vous voulez télécharger un programme ?
A l'aide de l'URL fourni sous forme d'une chaîne de caractères, le serveur va localiser le fichier voulu et va vous renvoyer les octets encodant le programme (que ce soit un code-source ou un code binaire).
1 |
|
La suite de l'activité n'est qu'un mini-TP totalement optionnel pour la NSI : la seule chose attendue aujourd'hui est de comprendre qu'un programme (ou une fonction) n'est qu'une donnée comme une autre. Donnée qui peut être traitée par un autre programme. Nous l'avons vu de façon conceptuelle.
La suite de l'activité montre concrétement :
- Partie 2 : qu'on peut envoyer des données à une fonction sans nécessairement leur attribuer un nom de paramètre précis
- Partie 3 : qu'on peut envoyer des données à un programme lors de son appel
- Partie 4 : qu'on peut donc créer un interpréteur : un programme qui lit un code source pour réaliser des actions
- Partie 5 : qu'on peut donc envoyer un programme à notre interpréteur
Mais tout ceci est optionnel. C'est juste pour vous montrer comment cela peut fonctionner.
2 - Envoyer des données à une fonction
Vous savez qu'on peut envoyer des données à une fonction en fournissant des argumnets qui seront stockés dans les paramètres.
01° Utiliser le programme ci-dessous en le sauvegardant sous le nom "transfert.py".
Faire quelques tests pour vous convaincre qu'on parvient bien ) transmettre les arguments fournis (normalement, à ce nouveau là de la NSI, la question devrait vous paraître stupide...).
1
2
3
4
5
6 |
|
>>> %Run transfert.py
>>> addition(5,10)
5
10
15
En réalité, on peut transférer autant d'arguments qu'on veut à une fonction et elle peut alors les stocker dans autant de paramètres qu'il le faut.
Pour récupérer ces arguments supplémentaires, il faut indiquer un paramètre assez particulier : un paramètre qui commence par une étoile. Habituellement, on le nomme *args. En Python, il s'agit alors d'un tuple qui va récupérer tous les arguments qu'on a pas pu placer dans les arguments définis "normalement".
02° Utiliser le programme ci-dessous en le sauvegardant sous le nom "transfert.py".
1
2
3
4
5
6
7
8
9
10
11 |
|
Question :
Qu'est-ce qui montre que *args est bien un tuple en Python ?
>>> %Run transfert.py
>>> addition(5,10)
5
10
()
15
>>> addition(5,10,20,30,40)
5
10
(20, 30, 40)
105
Si on veut garder une belle fonction, il faudra par contre expliquer qu'on ne veut que des entiers par exemple.
Nous ne sommes même pas obligés de garder a et b d'ailleurs : on pourrait juste faire ceci mais rien ne garantit en réalité que la réponse soit bien un intéger :
1
2
3
4
5
6
7
8 |
|
>>> %Run transfert.py
>>> addition(5,10,20,30,40)
(5, 10, 20, 30, 40)
105
On peut donc transférer des arguments non nommés à une fonction.
Mais on peut aussi transmettre des arguments nommés sans que la fonction n'ai besoin de les avoir clairement dans ces paramètres.
Il faut alors prévoir un paramètre particulier qui va recevoir tous les arguments nommés non déclarés. Le nom de ce paramètre particulier doit commencer par deux étoiles. On le nomme habituellement **kwargs.
03° Utiliser le programme ci-dessous en le sauvegardant sous le nom "transfert.py".
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 |
|
Question :
Qu'est-ce qui montre que **kwargs est bien un dictionnaire en Python ?
>>> %Run transfert.py
>>> calculer(5,10, operation='+')
(5, 10)
{'operation': '+'}
15
>>> calculer(5,10, operation='*', la_reponse=42)
(5, 10)
{'operation': '*', 'la_reponse': 42}
50
3 - Envoyer des données à un programme
Pourquoi parler de *args et **kwargs alors que ce ne sont pas des attendus d'un élève de NSI ? Pour vous montrer qu'il existe des mécanismes capables de récupérer les arguments non explicites fournies à une fonction.
Et on peut faire la même chose avec nos programmes...
Finalement, un processus peut être vue comme une sorte de fonction exécutée par le processus-parent, non ?
Pour l'instant, l'appel au programme a été fait sous cette forme :
>>> %Run transfert.py
Mais on pourrait aussi faire ceci :
>>> %Run transfert.py 5 10
On pourrait ainsi fournir directement des données au programme : l'interpréteur Python est activé avant %Run et on lui envoie des arguments, à savoir :
- Le nom du script à interpréter : transfert.py
- Un premier argument : 5
- Un deuxième argument : 10
Pour visualiser ceci avec Python, nous allons devoir utiliser le module sys qui permet d'interagir avec le système d'exploitation. Souvenez-vous que c'est lui qui gère les processus et donc l'exécution effective des programmes.
04° Utiliser le programme ci-dessous en le sauvegardant sous le nom "transfert.py". Faire différents appels pour visualiser qu'on parvient bien à lui envoyer des données et pas simplement lui demander de tourner avec ces données internes.
1
2
3
4
5 |
|
Questions :
- Qu'est-ce qui montre que sys.argv est un tableau en Python ?
- Quel est le type du 5 une fois reçu pour le programme ?
>>> %Run transfert.py
['transfert.py']
>>> %Run transfert.py 5
['transfert.py', '5']
>>> %Run transfert.py 5 10
['transfert.py', '5', '10']
>>> %Run transfert.py * 5 10
['transfert.py', '*', '5', '10']
>>> %Run transfert.py + 5 10
['transfert.py', '+', '5', '10']
05° Réaliser la fonction calculer qui permettra au PROGRAMME d'afficher les résultats demandées (voir les exemples d'appels du programme).
Je ne m'intéresse pas ici à la manière de récupérer la réponse d'un programme pour l'envoyer à un autre programme. On se contentera pour l'instant d'un simple print.
De la même façon, on ne fera aucune vérification des données envoyées. En terme de solidité du code créé, c'est pour joyeux...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
|
>>> %Run transfert.py
>>> %Run transfert.py + 5 10
15
>>> %Run transfert.py * 5 10
50
>>> %Run transfert.py * 5 10 10
500
...CORRECTION...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 |
|
4 - Réaliser notre propre interpréteur
5 - Envoyer un programme à notre interpréteur
Activité publiée le 30 03 2021
Dernière modification : 06 04 2021
Auteur : ows. h.