On va s'entraîner aux modules.
mon_module, pour le moment vide, qui existe en plus du module main.mon_module, créer la variable salutation qui vaut la str "Bonjour depuis ", suivi du
véritable nom du module et pas juste le nom du module écrit "en dur" dans la chaîne.
main, afficher la variable salutation de mon_module.Fichier mon_module.py:
# __name__ est une variable pré-existante dans TOUT module,
# qui contient automatiquement le nom du module.
salutation = "Bonjour depuis " + __name__
Fichier main.py (dans le même dossier que mon_module.py):
# ↓ On ne met PAS .py après le nom du module.
import mon_module
# ↓ On peut accéder ainsi aux variables globales de mon_module
# (globales signifie définies en dehors de toute fonction, classe ou autre structure)
print(mon_module.salutation)
Si on exécute main.py (ce qui est le cas quand on appuie sur le bouton "Run" dans replit), on obtient:
Bonjour depuis mon_module
>
On va continuer de s'entraîner aux modules.
Dans mon_module, créer la fonction afficher_salutation(), qui ne prend aucun paramètre, ne retourne aucun résultat, et qui
lors de son exécution affiche la variable salutation.
Depuis le module main, ne plus afficher la variable salutation directement, mais exécuter
afficher_salutation() de mon_module.
Fichier mon_module.py:
salutation = "Bonjour depuis " + __name__
def afficher_salutation():
print(salutation)
Fichier main.py (dans le même dossier que mon_module.py):
import mon_module
# ↓ On peut appeler une fonction de mon_module
mon_module.afficher_salutation()
Si on exécute main.py (ce qui est le cas quand on appuie sur le bouton "Run" dans replit), on obtient:
Bonjour depuis mon_module
>
On va continuer de s'entraîner aux modules.
(Cette question donne des instructions spécifiques à replit, pour ceux qui utilisent VSCode ou qui utilisent la console, vous pouvez choisir directement quel fichier Python vous exécutez, c'est donc un peu plus simple et vous pouvez ignorer les instructions pour replit. Donc au lieux d'utiliser le shell comme dans replit, lancez simplement le fichier Python demandé en utilisant la façon dont vous avez l'habitude.)
A côté de l'onglet "Console" dans replit, vous avez l'onglet "Shell". Dans le shell, vous pouvez écrire des commandes au niveau du système
d'exploitation (Linux) sur le serveur de replit dans lequel Python est installé. Il vous est ainsi possible d'exécuter la commande de Python. Cette
commande est bien plus pratique que le bouton "Run" dont vous avez l'habitude. Le bouton Run lance la commande suivante dans le shell: python
main.py, c'est à dire le mot "python" suivi d'un espace, suivi du nom du fichier .py à exécuter.
main. Vérifiez que vous obtenez bien la même chose qu'avec Run.
python main.py. Puis appuyer sur la touche Entrée.
Bonjour depuis mon_module
>
mon_module (astuce: avec le curseur qui clignote dans le shell, appuyer une ou plusieurs
fois sur la touche du clavier "flêche du haut" vous permet de remonter dans l'historique des commandes que vous avez entrées précédemment). Vous
ne devriez rien voir s'afficher, pourquoi?
Ecrire dans le shell la commande: python mon_module.py. Puis appuyer sur la touche Entrée.
Rien de spécial ne s'affiche dans le shell.
mon_module, ajouter un appel à afficher_salutation(), et re-exécuter mon_module
depuis le shell. Vous devriez voir la salutation un peu différente. Que voyez-vous, et pourquoi?
Fichier mon_module.py:
salutation = "Bonjour depuis " + __name__
def afficher_salutation():
print(salutation)
# ↓ On a rajouté cet appel
afficher_salutation()
Ecrire dans le shell la commande: python mon_module.py. Puis appuyer sur la touche Entrée.
Bonjour depuis __main__
>
Le nom du module est __main__ désormais parce que c'est le nom que Python donne automatiquement au module qui est
exécuté en premier, celui par lequel on lance le programme tout entier. Jusqu'à présent dans replit, le fichier qui a toujours été
exécuté en premier a été main.py, mais Python n'oblige en rien cela, c'est juste une convention de replit. Tout module,
c'est à dire tout fichier .py, peut être exécuté directement par la commande Python.
main, quelque chose a également changé par rapport à la question 2. Qu'est-ce, et pourquoi?
Ecrire dans le shell la commande: python main.py. Puis appuyer sur la touche Entrée.
Bonjour depuis mon_module
Bonjour depuis mon_module
>
On voit DEUX affichages désormais. Le premier est parce que lorsqu'on importe mon_module il est exécuté, donc y compris
l'appel à afficher_salutation() qu'on a rajouté à la question précédente. Puis le second affichage est parce que dans
main.py on fait aussi un appel à mon_module.afficher_salutation().
Adapter le code dans mon_module pour faire en sorte que:
mon_module directement avec la commande python depuis le shell, on voit la salutationmain, on ne voit qu'une seule salutation: celle de l'appel de la fonction dans main
(si la salutation est différente dans les 2 cas, c'est normal et on n'en tient pas compte)
Fichier mon_module.py:
salutation = "Bonjour depuis " + __name__
def afficher_salutation():
print(salutation)
# ↓ On a rajouté le "if". Le test est: si le nom du module est égal à la str
# "__main__", cela signifie alors que le module est exécuté directement par la commande
# python, et alors on exécute la fonction afficher_salutation.
# Sinon ça signifie que le module est exécuté par importation depuis un autre module,
# et dans ce cas on ne fait rien de spécial.
if __name__ == "__main__":
afficher_salutation()
Ecrire dans le shell la commande: python mon_module.py. Puis appuyer sur la touche Entrée.
Bonjour depuis __main__
>
Ecrire dans le shell la commande: python main.py. Puis appuyer sur la touche Entrée.
Bonjour depuis mon_module
>
On va s'entraîner aux dictionnaires. Vous pouvez supprimer tout le code précédent dans le module main.
main, créer un dictionnaire vide et le mettre dans une variable dico_1."une clé" associée à la valeur "sa valeur"8.2 associée à la valeur "autre valeur"True associée à la valeur 50dico_1 (utiliser l'écriture litérale
des dict, ne pas faire de copie) et le mettre dans une variable dico_2.
dico_1 en entier sur une ligne et en une seule action, et faire de même pour dico_2 sur une seconde ligne.
8.2 de dico_1.dico_2 de tout son contenu en une seule action.Fichier main.py:
# 1
dico_1 = {}
# 2
dico_1["une clé"] = "sa valeur"
# 3
dico_1[8.2] = "autre valeur"
# 4
dico_1[True] = 50
# 5
print("q5:", dico_1["une clé"])
print("q5:", dico_1[8.2])
print("q5:", dico_1[True])
# 6
for clé, valeur in dico_1.items():
print("q6:", clé, "=", valeur)
# 7
dico_2 = {"une clé": "sa valeur", 8.2: "autre valeur", True: 50}
# 8, 9
print("q9 dico_1:", dico_1)
print("q9 dico_2:", dico_2)
# 10
del dico_1[8.2]
# 11
dico_2.clear()
# 12
print("q12 dico_1:", dico_1)
print("q12 dico_2:", dico_2)
q5: sa valeur
q5: autre valeur
q5: 50
q6: une clé = sa valeur
q6: 8.2 = autre valeur
q6: True = 50
q9 dico_1: {'une clé': 'sa valeur', 8.2: 'autre valeur', True: 50}
q9 dico_2: {'une clé': 'sa valeur', 8.2: 'autre valeur', True: 50}
q12 dico_1: {'une clé': 'sa valeur', True: 50}
q12 dico_2: {}
>
On va s'entraîner aux paramètres des fonctions. Vous pouvez supprimer tout le code précédent dans le module main.
Dans le module main, déclarer une fonction dire_bonjour, qui lors de son exécution affichera une salutation de la forme:
L'introduction, le nom, et la question seront passés en paramètre de la fonction:
A l'aide d'appels à la fonction dire_bonjour, afficher dans la console:
Fichier main.py:
# Deux paramètres ont une valeur par défaut, ce qui permettra de ne pas les
# spécifier au moment de l'appel de la fonction si leur valeur par défaut convient.
def dire_bonjour(introduction, nom="Toto", question="Quel est votre nom?"):
print(introduction + ". Je m'appelle " + nom + ". Et vous? " + question)
# 1 ↓ On utilise la valeur par défaut des paramètres nom et question
dire_bonjour("Bonjour")
# Forme alternative
# ↓ On peut nommer même les paramètres sans valeur par défaut si on le souhaite
# dire_bonjour(introduction="Bonjour")
# 2 ↓ On spécifie une autre valeur que celle par défaut pour le paramètre nom
# mais on utilise toujours la valeur par défaut du paramètre question.
dire_bonjour("Bonjour", "Titi")
# Formes alternatives
# dire_bonjour("Bonjour", nom="Titi")
# dire_bonjour(introduction="Bonjour", nom="Titi")
# ↓ L'ordre des paramètres nommés ne compte pas
# dire_bonjour(nom="Titi", introduction="Bonjour")
# 3
dire_bonjour("Bonjour", question="D'où venez-vous?")
# Forme alternative
# dire_bonjour(introduction="Bonjour", question="D'où venez-vous?")
# 4
dire_bonjour("Salut", "Titi", "D'où venez-vous?")
# Forme alternative
# ↓ L'ordre des paramètres nommés ne compte pas,
# mais il reste primordial pour ceux non nommés.
# dire_bonjour("Salut", question="D'où venez-vous?", nom="Titi")
Bonjour. Je m'appelle Toto. Et vous? Quel est votre nom?
Bonjour. Je m'appelle Titi. Et vous? Quel est votre nom?
Bonjour. Je m'appelle Toto. Et vous? D'où venez-vous?
Salut. Je m'appelle Titi. Et vous? D'où venez-vous?
>
On va s'entraîner à la visibilité et portée des variables. Vous pouvez supprimer tout le code précédent dans les modules main et mon_module.
main, créer une variable globale var_1 qui vaut 10.main, créer une variable globale var_2 qui vaut "cool".main, créer une fonction hello qui prend 2 paramètres a et b, et qui dans son
corps crée une variable locale var_1 qui vaut 1, puis retrouve toutes ses variables locales avec la fonction prévue pour
ça et les affiche.
mon_module, créer une variable globale a qui vaut 20.mon_module, créer une variable globale b qui vaut False.mon_module, créer une fonction bidule prend 2 paramètres x et y, et
qui dans son corps:
aa qui vaut 30x, y et aa à la variable globale amain, afficher en une seule action tous les identifiants globaux, ainsi que leur valeur. Vérifiez que vous retrouvez bien
tout ce que vous avez créé dans main.
mon_module. Vérifiez que vous retrouvez bien tout ce que vous avez créé dans
mon_modulemain.hello. Quels identifiants voyez-vous? Est-ce normal?main.var_1 a-t'elle été modifiée? Pourquoi?mon_module.bidule. Quels identifiants voyez-vous? Est-ce normal?mon_module.a a-t'elle été modifiée? Pourquoi?Fichier main.py:
var_1 = 10
var_2 = "cool"
def hello(a, b):
# ↓ Cette variable est locale, et est différente de la globale var_1
var_1 = 1
print("Variables locales dans hello:", locals())
print("Variables globales dans main AVANT l'appel à hello():", globals())
hello(5, 6)
print("Variables globales dans main APRÈS l'appel à hello():", globals())
Ecrire dans le shell la commande: python main.py. Puis appuyer sur la touche Entrée.
Variables globales dans main AVANT l'appel à hello(): {
'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f128c8ea7c0>,
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
'__file__': 'main.py', '__cached__': None,
'var_1': 10, 'var_2': 'cool', 'hello': <function hello at 0x7f128b281820>
}
Variables locales dans hello: {
'a': 5, 'b': 6, 'var_1': 1
}
Variables globales dans main APRÈS l'appel à hello(): {
'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f128c8ea7c0>,
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
'__file__': 'main.py', '__cached__': None,
'var_1': 10, 'var_2': 'cool', 'hello': <function hello at 0x7f128b281820>
}
>
(↑ L'affichage a été un peu formatté pour mieux voir l'information qui nous intéresse)
On peut voir que la fonction hello() a 3 variables locales: a, b et var_1. Et on note
aussi que var_1 dans hello() vaut 1, mais var_1 globale vaut toujours 10, preuve que ce sont deux
variables différentes, même si elles ont le même nom, elles n'existent pas dans le même espace de nommage.
Remarquez aussi que les paramètres a et b sont aussi considérés comme des variables locales au sein de leur
fonction.
Fichier mon_module.py:
a = 20
b = False
def bidule(x, y):
# ↓ On déclare qu'on veut modifier la variable globale a depuis l'intérieur de la fonction
# grâce au mot-clé "global". Si on aurait écrit directement a = ..., alors ça créerait une variable locale a.
global a
aa = 30
a = x + y +aa
print("Variables locales dans bidule:", locals())
print("Variables globales dans mon_module AVANT l'appel à bidule():", globals())
bidule(5, 6)
print("Variables globales dans mon_module APRÈS l'appel à bidule():", globals())
Ecrire dans le shell la commande: python mon_module.py. Puis appuyer sur la touche Entrée.
Variables globales dans mon_module AVANT l'appel à bidule(): {
'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f44b41867c0>,
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
'__file__': 'mon_module.py', '__cached__': None,
'a': 20, 'b': False, 'bidule': <function bidule at 0x7f44b2b1dca0>
}
Variables locales dans bidule: {
'x': 5, 'y': 6, 'aa': 30
}
Variables globales dans mon_module APRÈS l'appel à bidule(): {
'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f44b41867c0>,
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
'__file__': 'mon_module.py', '__cached__': None,
'a': 41, 'b': False, 'bidule': <function bidule at 0x7f44b2b1dca0>
}
>
(↑ L'affichage a été un peu formatté pour mieux voir l'information qui nous intéresse)
On remarque qu'après l'appel à bidule() la variable globale a a bien été modifiée, et que celle-ci n'apparaît pas
dans liste des variables locales à bidule().
Pour répondre aux questions de l'exercice:
9. Lors de l'appel à main.hello() on voit les identifiants "a", "b" et "var_1", et c'est normal car tous trois sont des
variables locales, et c'est ce qu'on voulait afficher avec l'appel à la fonction prédéfinie locals().
10. Non la variable globale main.var_1 n'a pas été modifiée lors de l'appel à main.hello() et c'est normal, car
toute variable globale est accessible en lecture depuis l'intérieur d'une fonction, mais pas en écriture. Lorsqu'on tente de modifier une
variable globale depuis l'intérieur d'une fonction cela crée automatiquement une variable locale portant le même nom que la globale.
11. Lors de l'appel à mon_module.bidule() on voit les identifiants "x", "y" et "aa", et c'est normal car tous trois sont des
variables locales, et c'est ce qu'on voulait afficher avec l'appel à la fonction prédéfinie locals(). On ne voit pas la
variable a car c'est une variable globale.
12. Oui a a été modifiée lors de l'appel à mon_module.bidule() car on l'a bien déclarée comme variable globale à
l'intérieur de la fonction avant de la modifier.
On va s'entraîner à la différence entre la modification des variables elles-mêmes et la modification des objets pointés par les variables. Vous
pouvez supprimer tout le code précédent dans les modules main et mon_module. Dans le module main:
liste_globaleajout_liste qui prend un paramètre (qui sera de n'importe quel type de donnée), et qui à chaque appel ajoute la
valeur de son paramètre à la fin de liste_globale. La fonction ne retourne rien.
ajout_liste() et vérifier ensuite que ça fonctionne, c'est-à-dire la liste pointée par la variable globale
liste_globale a bien les éléments ajoutés dedans après les appels.
nb_global qui vaut 0ajout_nombre_1 qui prend un paramètre (qui devra être un int ou float), et qui à chaque
appel ajoute la valeur de son paramètre à nb_global. La fonction ne retourne rien.
ajout_nombre_2 qui prend un paramètre (qui devra être un int ou float), et qui ne
modifie pas nb_global, mais retourne la somme de nb_global + celle de son paramètre.
ajout_nombre_1() et vérifier ensuite que ça fonctionne, c'est-à-dire nb_global est modifié correctement avec
la somme.
ajout_nombre_2(). Quelle différence y-a t'il avec ajout_nombre_1(), et pourquoi?ajout_liste() et les 2 fonctions ajout_nombre() pour modifier la valeur de
variables globales, et pourquoi cette différence?
Fichier main.py:
liste_globale = []
def ajout_liste(valeur):
liste_globale.append(valeur)
# 3
ajout_liste("Coucou")
ajout_liste("Bonjour")
print(liste_globale)
nb_global = 0
def ajout_nombre_1(nb):
global nb_global
nb_global += nb
def ajout_nombre_2(nb):
return nb_global + nb
print("1:", nb_global)
# 7
ajout_nombre_1(1)
print("2:", nb_global)
# 8
nb_global = ajout_nombre_2(1)
print("3:", nb_global)
['Coucou', 'Bonjour']
1: 0
2: 1
3: 2
>
8. ajout_nombre_2() utilise la variable globale nb_global mais ne la modifie pas. ajout_nombre_1() par
contre la modifie (avec +=), donc il faut utiliser le mot-clé global. Comme ajout_nombre_2() ne
modifie pas nb_global, si on veut le faire on est obligé de le faire en dehors de la fonction, comme à la ligne 23 par exemple,
contrairement à ajout_nombre_1() lors de son appel à la ligne 20.
9. Les deux fonctions ajout_liste() et ajout_nombre_1() semblent faire la même chose: elles modifient la valeur des
variables globales, non? FAUX! Ils y a une GROSSE différence entre les deux.
Remarquez que le mot-clé global dans ajout_liste() n'est pas présent, hors on voit dans l'affichage que liste_globale
est bien modifiée lors des appels à la fonction. Il est primordial de comprendre que ajout_liste() ne modifie pas la VARIABLE,
mais l'OBJET pointé par la variable à travers sa méthode append(). liste_globale pointe toujours vers la même
liste en mémoire, la variable n'est donc pas modifiée, mais l'objet liste lui s'est modifié en s'ajoutant un nouvel élément.
Aurait-on pu faire pareil avec ajout_nombre_1()? Ne pas modifier la variable mais plutôt l'objet nombre vers lequel il pointe?
Non, car rappelez-vous, une liste (de type list) est muable, mais les objets de type int et float
sont immuables, ils ne peuvent donc jamais être modifiés. Si on veut qu'une variable pointe vers un nombre différent, on ne modifie pas
l'objet en question contrairement à une liste, mais on fait pointer la variable vers un tout autre objet nombre en mémoire, avec
l'instruction =.
Vous pouvez supprimer tout le code précédent dans les modules main et mon_module. Dans le module main:
mathpi du module mathdegrees du module math, qui change des radians passés en paramètres, vers des degrésradians, qui change des degrés en radianscos et sin. Les paramètres sont en radians.pow qui donne le premier paramètre à la puissance du second paramètre. Peut-on calculer la puissance d'un nombre
autrement?
sqrt qui donne la racine carrée de son paramètre. Peut-on avoir la racine carrée d'un nombre autrement? Et la
racine cubique?
Fichier main.py:
# 1
import math
# 2
print("2:", math.pi)
# 3
# ↓ On peut facilement le calculer soi-même sans passer par cette fonction. Comment?
print("3:", math.degrees(math.pi))
# 4
# ↓ On peut facilement le calculer soi-même sans passer par cette fonction. Comment?
print("4:", math.radians(180))
# 5
# ↓ Le résultat se rapproche de zéro, mais n'est pas exactement zéro.
# Cela est dû à la représentation interne des nombres à virgules qui a une précision limitée.
print("5:", math.cos(math.pi/2))
print("5:", math.sin(math.pi/2))
# 6
print("6:", math.pow(2, 3))
print("6:", 2**3) # cette version est plus courte et revient au même
# 7
print("7:", math.sqrt(16))
print("7:", 16**0.5) # cette version est plus courte et revient au même
print("7:", 8**(1/3)) # pour avoir la racine cubique on fait puissance 1/3
2: 3.141592653589793
3: 180.0
4: 3.141592653589793
5: 6.123233995736766e-17
5: 1.0
6: 8.0
6: 8
7: 4.0
7: 4.0
7: 2.0
>
Dans un nouveau fichier Python, créer un programme qui crée un nouveau fichier texte, et y écrit le texte "Bonjour depuis Python" dedans.
Puis à l'aide d'une boucle, écrire ce texte 1000 fois dans le fichier texte qui doit donc avoir au final 1000 lignes.
# ↓ On crée le fichier avec la fonction open et le mode "w" pour 'write'.
# ↓ On précise aussi le paramètre "encoding" pour que le fichier supporte
# tous les caractères de toutes les langues du monde.
fichier = open("Fichier créé par Python.txt", "w", encoding="utf-8")
for no_ligne in range(1000):
# ↓ On écrit dans le fichier avec la méthode write de l'objet référencé
# par la variable "fichier".
# ↓ On n'oublie pas le caractère saut de ligne \n pour bien voir des
# lignes dans le fichier texte généré, car write ne saute pas de ligne
# automatiquement pour nous.
fichier.write("Bonjour\n")
# ↓ On n'oublie pas de fermer le fichier pour que Python l'enregistre
# correctement une fois qu'on a fini d'écrire dedans.
fichier.close()