Formation permanente du CNRS, Délégation Alsace
Février - Mars 2017
Auteurs :
Contenu sous licence CC BY-SA 4.0
# Avec des nombres entiers
print(16 / 3) # Quotient de la division euclidienne (produit un réel)
print(16 // 3) # Quotient de la division euclidienne (produit un entier)
print(16 % 3) # Reste de la division euclidienne (produit un entier)
# Avec des nombres flottants
print(16. / 3) # Division (produit un réel)
print(16. // 3) # Quotient de la division (produit un réel)
print(16. % 3) # Reste de la division ou modulo (produit un réel)
print(2 ** 10)
# On peut aussi utiliser la fonction pow() du module math, mais celui-ci renvoie un réel...
import math
print(math.pow(2, 10))
and, or, not
print(True or False)
print(True and False)
print(not True)
print(not False)
print(not [])
print(not (1, 2, 3))
Attention, ce sont des opérateurs "court-circuit" :
a = True
b = False and a # b vaut False sans que a soit évalué
c = True or a # c vaut True, sans que a soit évalué
Pour s'en convaincre :
True or print("nicht a kurz schluss")
False and print("not a short circuit")
print('on a prouvé que ce sont des opérateurs "court-circuit"...')
Exercice : Modifiez les valeurs True et False dans la cellule précédente, pour visualiser le fonctionnement de ces opérateurs.
==, is, !=, is not, >, >=, <, <=
L'évaluation de ces opérateurs retourne une valeur booléenne.
print(2 == 2)
print(2 != 2)
print(2 == 2.0)
print(type(2) is int)
On peut utiliser ces opérateurs avec des variables et des appels à des fonctions.
x = 3
print(1 > x)
y = [0, 1, 42, 0]
print(x <= max(y))
print(x <= min(y))
On peut chaîner ces opérateurs, mais ils fonctionnent en mode "court-circuit" et l'opérande central n'est évaluée qu'une seule fois.
x = 3
print(2 < x <= 9) # équivalent à 2 < x and x <= 9
Attention : comparer des types non numériques peut avoir des résultats surprenants.
# Chaînes de caractères
print("aaa" < "abc")
print("aaa" < "aaaa")
print("22" > "3.0")
# Listes
print([1, 2, 3, 4] > [42, 42])
print([666] > [42, 42])
Attention : comparer des types incompatibles peut avoir des résultats surprenants.
# Cette cellule génère des erreurs
print('chaîne:\t', "a" < 2)
print('liste:\t', ["zogzog"] > 42)
print('vide:\t', [] > 1)
print('tuple:\t', [23, 24] >= (23, 24))
print('dict:\t', [23, 24] >= {23: True, 24: "c'est pas faux"})
Attention, l'égalité de valeur n'implique pas forcément que l'identité des objets comparés est la même.
a = []
b = []
c = a
print(a == b) # comparaison de valeur
print(a is b) # test d'identité
Mais des variables différentes peuvent référencer le même objet.
print(a == c) # comparaison de valeur
print(a is c) # test d'identité
|, ^, &, <<, >>, ~
Ces opérateurs permettent de manipuler individuellement les bits d'un entier.
Ce sont des opérations bas-niveau, souvent utilisées pour piloter directement du matériel, pour implémenter des protocoles de communication binaires (par exemple réseau ou disque).
L'utilisation d'entiers comme ensemble de bits permet des encodages de données très compacts, un booléen (True, False) ne prendrait qu'un bit en mémoire, c'est a dire que l'on peut encoder 64 booléens dans un entier.
Description complète ici.
val = 67 # == 64 + 2 + 1 == 2**6 + 2**1 + 2**0 == 0b1000011
print(bin(val))
mask = 1 << 0 # On veut récupérer le 1er bit
print('le 1er bit vaut', (val & mask) >> 0)
mask = 1 << 1 # On veut récupérer le 2ème bit
print('le 2ème bit vaut', (val & mask) >> 1)
mask = 1 << 2 # On veut récupérer le 3ème bit
print('le 3ème bit vaut', (val & mask) >> 2)
mask = 1 << 6 # On veut récupérer le 7ème bit
print('le 7ème bit vaut', (val & mask) >> 6)
# Si on positionne le 4ème bit a 1 (on rajoute 2**3 = 8)
newval = val | (1 << 3)
print(newval)
# Si on positionne le 6ème bit a 0 (on soustrait 2**7 = 64)
print(newval & ~(1 << 6))
Exercice : Retournez une chaîne de caractères représentant le nombre contenu dans
var
écrit en notation binaire. Par exemple:5 -> '101'
6 -> '110'
7 -> '111'
var = 7
# votre code ici
Solution : exos/num2bin.py
+= -= /=
a = 4
a += 1 # <=> a = a + 1
print(a)
a //= 2
print(a)
a **= 3
print(a)
a %= 2
print(a)
Python effectue certaines conversions implicites, quand cela ne perd pas d'information (par ex. de entier court vers entier long).
print(1 + 0b1)
print(1 + 1.0)
print(1.0 + 2 + 0b11 + 4j)
Mais dans d'autres cas, la conversion doit être explicite.
# Cette cellule génère une erreur
print(1 + '1')
Exercice :
Sans enlever le '+':
- Corrigez le code de la cellule ci dessus, afin d'afficher la chaine 11
- Corrigez le code de la cellule ci dessus, afin d'afficher le nombre 2
- Corrigez le code de la cellule ci dessus, afin d'afficher le nombre 11
Solution : exos/type_conv.py
Les opérateurs ont en python des priorités classiques.
Par exemple, dans l'ordre:
**
*
et /
+
et -
etc...
Utilisez des parenthèses quand cela aide a la lisibilité et à la clarté.
Une priorité explicitée avec des parenthèses est souvent plus facile à relire que s'il n'y en a pas et qu'il faut se remémorer les règles.
Pour plus d'informations, voir ici
pass
if/elif/else
for elt in liste
for idx in range(len(liste))
while
break
continue
{}
en java et C++). Cela permet de rendre le code plus compact.if True:
print("toutes")
print("les")
print("lignes")
print("au même niveau d'indentation forment un bloc de code")
print('et quand on remonte, on "termine" un bloc de code')
Exercice : changez le True en False, et observez quelles lignes de code ne sont plus exécutées.
Pass
¶En cas de besoin d'un bloc de code qui ne fait rien, on utilise le mot clé pass
(équivalent à NOP ou NO-OP)
condition = True
while condition:
pass
Les instructions if/elif/else
permettent d'exécuter des blocs d'instructions en fonction de conditions :
if <test1>:
<bloc d'instructions 1>
[elif <test2>:
<bloc d'instructions 2>]
[else:
<bloc d'instructions 3>]
Pour les connaisseurs elif
est similaire au switch
en C et C++...
if True:
print("c'est vrai!")
if False:
print("je suis caché!")
else:
print("mais moi je suis en pleine lumière...")
# Pour cet exemple, on itère sur les éléments d'un tuple (cf. boucle for plus loin)
for position in 2, 9, 3, 1, 8:
if position == 1:
print(position, "Or")
elif position == 2:
print(position, "Argent")
elif position == 3:
print(position, "Bronze")
else:
print(position, "Vestiaires")
taille = 1.90
if taille >= 1.70: # La taille moyenne en France
print('grand')
else:
print('petit')
Exercices :
- Editez la cellule pour y mettre votre taille et exécutez-la pour savoir si vous êtes grand ou petit.
- Gérez le cas des gens de taille moyenne.
- Utilisez la fonction input() pour demander sa taille à l'utilisateur.
Solution : exos/taille.py
Les boucles sont les structures de contrôle permettant de répéter l'exécution d'un bloc de code plusieurs fois.
while
¶La plus simple est la boucle de type while
:
while <condition>:
<bloc d'instructions 1>
<bloc d'instructions 2>
Tant que <condition>
est True, le <bloc d'instructions 1>
est exécuté, quand la condition passe à False, l'exécution continue au <bloc d'instructions 2>
.
compteur = 3
while compteur > 0:
print('le compteur vaut :', compteur)
compteur = compteur - 1
print('le compteur a été décrémenté 3 fois et vaut maintenant', compteur)
Exercice :
- Ecrivez une boucle
while
qui décompte les secondes pour la soirée du réveillon.- Allez voir par ici pour passer le temps...
# Votre code ici
Solution : exos/decompte.py
for
¶Une boucle plus complexe : for/in
for <variable> in <iterable>:
<bloc d'instructions 1>
<bloc d'instructions 2>
A chaque tour de boucle, la variable <variable>
va référencer un des éléménts de l'<iterable>
. La boucle s'arrête quand tous les éléménts de l'itérable ont été traités. Il est fortement déconseillé de modifier l'itérable en question dans le <bloc d'instructions 1>
.
invites = ('Aline', 'Bernard', 'Céline', 'Dédé')
for personne in invites:
print('Bonjour %s, bienvenue à la soirée de gala !' % personne)
print('Maintenant tout le monde à été bien accueilli...')
Exercice : Rajoutez des invités à la fête. Vérifiez que tout le monde est accueilli correctement.
# Maintenant, si nous avons reçu des réponses à notre invitation et stocké ceux qui ne peuvent pas venir
invites = {'Aline': True, 'Bernard': False, 'Céline': True, 'Dédé': True}
for (personne, presence) in invites.items():
if presence:
print('Bonjour %s, bienvenue à la soirée de gala !' % personne)
else:
print('Malheureusement, %s ne sera pas avec nous ce soir.' % personne)
print('Maintenant tout le monde à été bien accueilli ou excusé...')
Exercice : Rajoutez des invités à la fête. Certains ayant répondu qu'ils ne pourraient pas venir. Vérifiez que tout le monde est accueilli ou excusé correctement.
nombres = [2, 4, 8, 6, 8, 1, 0, 1j]
for idx in range(len(nombres)):
nombres[idx] **= 2
# Les carrés
print(nombres)
Il existe une forme raccourcie pour faire ce genre de choses, la fonction interne enumerate()
nombres = [2, 4, 8, 6, 8, 1, 0]
for (idx, item) in enumerate(nombres):
nombres[idx] = bool(item % 2)
# Les impairs
print(nombres)
print(type(range(3))) # Like xrange() in python2
print(repr(range(3))) # Like xrange() in python2
print(type(list(range(3)))) # Like range in python2
break
¶Il est possible d'arrêter prématurément une boucle grâce a l'instruction break
.
L'instruction break
est utilisable indifférement dans les boucles for
ou while
.
compteur = 3
while True: # Notre boucle infinie
compteur -= 1
print('Dans la boucle infinie! compteur =', compteur)
if compteur <= 0:
break # On sort de la boucle while immédiatement
print('on contine, compteur =', compteur)
print("c'était pas vraiment une boucle infinie...")
En cas d'imbrication de plusieurs boucles, l'instruction break
sort de la plus imbriquée (la plus proche).
for i in (1, 2, 3):
for j in (1, 2, 3, 4):
if i == 2:
break
print("i, j = %d, %d" % (i, j))
continue
¶Si, dans une boucle, on veut passer immédiatement à l'itération suivante, on utilise l'instruction continue
.
compteur = 9
while compteur > 0:
compteur -= 1
if compteur % 2:
compteur /= 2
print('impair, on divise :', compteur)
continue # retourne immédiatement au début de la boucle
print("pair, RAS")
print("c'est fini...")
Les fonctions permettent de réutiliser des blocs de code plusieurs endroits différents sans avoir a copier ce bloc.
En python, il n'y a pas de notion de sous-routine. Les procédures sont gérées par les objets de type fonctions, avec ou sans valeur de retour.
def <nom fonction>(arg1, arg2, ...):
<bloc d'instructions>
return <valeur> # Instruction optionnelle
On distingue :
return
des fonctions sans return
()
est vide) des fonctions avec arguments (arg1, arg2, ...)
Pour définir une fonction :
def func(): # Definition de la fonction
print('You know what?')
print("I'm happy!")
Pour utiliser une fonction que l'on a défini :
func() # 1er Appel de la fonction
func() # 2eme appel
func() # 3eme appel, etc...
Exercice : Ecrivez une fonction nommée "rien" qui ne fait rien et appelez là deux fois.
# Votre code ici
Solution : exos/pass.py
return
¶def func(): # Definition de la fonction
return "I'm happy" # La fonction retourne une chaine de caractère
print("1er appel:")
func() # 1er Appel de la fonction : la valeur retournée n'est pas utilisée
print("2eme appel:")
ret_val = func() # Le retour du 2eme appel est stocké
print("La fonction func() nous a renvoyé la valeur:", ret_val)
Exercice : Ecrivez une fonction nommée "donne_rien" qui retourne la chaine de caractères 'rien'. Appelez-là et affichez sa valeur de retour.
# Votre code ici
Solution : exos/donne_rien.py
Pour définir une fonction qui prend des arguments, on leur donne juste des noms entre les parenthèses de la ligne def
. Ces paramètres seront définis comme des variables à l'intérieur de la fonction et recevrons les valeurs passées lors des appels de celle-ci.
def somme(x, y):
return x + y
Pour utiliser cette fonction avec diverses valeurs, il suffit de l'appeler plusieurs fois :
print(somme(1, 2))
print(somme(4, 7))
print(somme(2 + 2, 7))
print(somme(somme(2, 2), 7))
Exercice : Définissez une fonction nommée "chevalier", qui prend un paramètre, et qui répète (avec
chevalier(3)
dit bien Ni trois fois comme il convient !
Voici quelques exemples montrant comment cette fonction doit se comporter:
chevalier(1)
Ni!
chevalier(3)
Ni!Ni!Ni!
chevalier(6)
Ni!Ni!Ni!Ni!Ni!Ni!
# Votre code ici
# Vérifions que tout fonctionne bien:
#chevalier(1)
#chevalier(3)
#chevalier(6)
Solution : exos/chevalier.py
Exercice : Ecrivez une autre fonction, nommée "chevalier_ret", qui prend deux paramètres : un nombre et un booléen, et qui retourne une chaine de caractères constituée du nombre de répétitions de la chaine 'ni!' ou 'NI!' en fonction du paramètre booléen. Appelez cette fonction et affichez sa valeur de retour.
Voici quelques exemples montrant comment cette fonction doit se comporter:
a = chevalier(1, True)
print(a)
NI!
a = chevalier(3, False)
print(a)
ni!ni!ni!
a = chevalier(6, True)
print(a)
NI!NI!NI!NI!NI!NI!
# Votre code ici
# Vérifions que tout fonctionne bien:
#a = chevalier_ret(1, True)
#print(a)
#a = chevalier_ret(3, False)
#print(a)
#a = chevalier_ret(6, True)
#print(a)
Solution : exos/chevalier_ret.py
def somme(x, y=1):
return x + y
print(somme(1, 2))
print(somme(4)) # Si la valeur de y n'est pas spécifiée, le paramètre 'y' prend la valeur par défaut (ici : 1)
Note : Les arguments ayant une valeur par défaut doivent être placés en dernier.
print(somme(y=7, x=4)) # L'ordre peut être changé lors de l'appel si les arguments sont nommés
def func(*args):
print(args) # args est un tuple dont les éléments sont les arguments passés lors de l'appel
func("n'importe", "quel nombre et type de", "paramètres", 5, [1, 'toto'], None)
def func(**kwargs):
print(kwargs) # kwargs est un dictionnaire dont les éléments sont les arguments nommés passés lors de l'appel
func(x=1, y=2, couleur='rouge', epaisseur=2)
On peut combiner ce type d'arguments pour une même fonction :
def func(n, *args, **kwargs): # cet ordre est important
print("n =", n)
print("args =", args)
print("kwargs =", kwargs)
func(2, 'spam', 'egg', x=1, y=2, couleur='rouge', epaisseur=2)
def func1():
a = 1
print("Dans func1(), a =", a)
def func2():
print("Dans func2(), a =", a)
a = 2
func1()
func2()
print("Dans l'espace englobant, a =", a)
Cet exemple montre que :
func2()
).On veut illustrer le mécanisme de portée des variables au sein des fonctions :
def func():
a = 1
bbb = 2
print('Dans func(): a =', a)
a = 2
func()
print("Après func(): a =", a)
Les variables définies localement à l'intérieur d'une fonction sont détruites à la sortie de cette fonction. Ici, la variable b
n'existe pas hors de la fonction func()
, donc Python renvoie une erreur si on essaye d'utiliser b
depuis l'espace englobant :
# Cette cellule génère une erreur
print(bbb)
Ces fonctions sont disponibles dans tous les contextes. La liste complète est détaillée ici. En voici une sélection :
dir(obj)
: retourne une liste des toutes les méthodes et attributs de l'objet obj
dir()
: retourne une liste de tous les objets du contexte couranteval(expr)
: analyse et exécute la chaîne de caractère expr
a = 1
b = eval('a + 1')
print("b est de type", type(b), "et vaut", b)
globals()
: retourne un dictionnaire des variables présentes dans le contexte globallocals()
: idem globals()
mais avec le contexte localhelp(obj)
: affiche l’aide au sujet d’un objethelp()
: affiche l’aide générale (s'appelle depuis l'interpréteur interactif)input(prompt)
: retourne une chaîne de caractère lue dans la console après le message prompt
reponse = input('Ca va ? ') # Seule la variante input() fonctionne dans un notebook
if reponse.lower() in ('o', 'oui', 'yes', 'y', 'ok', 'da', 'jawohl', 'ja'):
print('Supercalifragilisticexpialidocious')
else:
print('Faut prendre des vacances...')
len(seq)
: retourne la longueur de la séquence seq
max(seq)
: retourne le maximum de la séquence seq
min(seq)
: retourne le minimum de la séquence seq
range([start=0], stop[, step=1])
: retourne une liste d'entiers allant de start
à stop - 1
, par pas de step
.print(list(range(10)))
print(list(range(5, 10, 2)))
repr(obj)
: affiche la représentation de l'objet obj
.reversed(seq)
: retourne l’inverse de la séquence seq
sorted(seq)
: retourne une séquence triée à partir de la séquence seq
sum(seq)
: retourne la somme des éléments de la séquence seq
Exercice 1
Ecrire une fonction
stat()
qui prend en argument une séquence d'entiers et retourne un tuple contenant :
- la somme
- le minimum
- le maximum
des éléments de la liste
def stat(a_list):
# votre fonction
pass
stat([1, 4, 6, 9])
Solution : exos/mystat.py
Exercice 2 :
Ecrire une fonction qui prend en paramètre une liste de prix hors taxes (HT) et qui retourne la somme toutes taxes comprises (TTC).
def ttc(liste_prix_ht):
# Votre fonction
pass
print(ttc([12, 56, 99, 1, 128]))
Solution : exos/ttc.py
Exercice 3 : Ecriture d'un wrapper de fonction
Noël pointe son nez, amusez-vous avec les boules de décoration !
Soit une fonction
boule()
capable d'accrocher une boule de couleur à la position(x, y)
d'un sapin.Exercice inspiré du Mooc de l'INRIA [Python : des fondamentaux à l'utilisation du langage](https://www.france-universite-numerique-mooc.fr/courses/inria/41001S02/session02/about)
def boule(x, y, couleur='bleue'):
print("J'accroche une boule en ({}, {}) de couleur {}".format(x, y, couleur))
# On place la première boule sur le sapin
boule(1, 2)
# Puis une autre, etc.
boule(3, 4)
Ecrire une fonction wrapper boule_or()
qui crée des boules dorées en appelant la fonction boule()
. Dans le futur, on souhaite modifier la fonction boule()
pour lui faire accepter un nouvel argument rendu (brillant, mat, etc.)
.
La fonction boule_or()
devra continuer à fonctionner après cette modification de la fonction boule()
et intégrer la nouvelle fonctionnalité rendu
sans qu'il soit nécessaire de la modifier.
def boule_or(x, y):
# Votre code ici
pass
# On place une boule en or sur le sapin
boule_or(2, 2)
Maintenant, on met à jour la fonction boule()
:
def boule(x, y, couleur='bleue', rendu='mat' ):
print("J'accroche une boule en ({}, {}) de couleur {} et de rendu {}.".format(x, y, couleur, rendu))
boule(1, 3, couleur='jaune', rendu='brillant')
Vérifier que votre fonction boule_or()
marche encore et gère la nouvelle fonctionnalité :
boule_or(3, 1, rendu='brillant') # doit retourner :
# J'accroche une boule en (3, 1) de couleur or et de rendu brillant.
Solution : exos/boule.py
Pour signaler des conditions particulières (erreurs, évenements exceptionnels), Python utilise un mécanisme de levée d'exceptions.
# Cette cellule génère une erreur
raise Exception
Ces exceptions peuvent embarquer des données permettant d'identifier l'évenement producteur.
# Cette cellule génère une erreur
raise Exception('Y a une erreur')
La levée d'une exception interrompt le cours normal de l'exécution du code et "remonte" jusqu'à l'endroit le plus proche gérant cette exception.
Pour intercepter les exceptions, on écrit :
try:
<bloc de code 1>
except Exception:
<bloc de code 2>
try:
print('ici ca fonctionne')
# ici on détecte une condition exceptionnelle, on signale une exception
raise Exception('y a un bug')
print('on arrive jamais ici')
except Exception as e:
# L'excécution continue ici
print("ici on peut essayer de corriger le problème lié à l'exception : Exception('%s')" % str(e))
print("et après, cela continue ici")
Exemple illustrant le mécanisme de remontée des exceptions d'un bloc à l'autre :
def a():
raise Exception('coucou de A')
def b():
print('début B')
a()
print('fini B')
try:
b()
except Exception as e:
print("l'exception vous envoie le message :", e)
Exercice : Ecrivez une fonction qui demande à l'utilisateur un fichier a ouvrir, et qui gère correctement les fichiers inexistants. Ensuite cette fonction affichera la première ligne du fichier. Finalement la fonction retournera une valeur booléenne indiquant que le fichier a été ouvert ou non.
Attention: sous windows, par defaut les extensions de fichier sont cachées...
# Votre code ici
Pour plus d'informations sur les exceptions, se référer ici
Pour faciliter la gestion des obligations liées à la libération de ressources, la fermeture de fichiers, etc... Python propose des gestionnaires de contexte introduits par le mot clé with
.
with open('interessant.txt', 'r') as fichier_ouvert:
# Dans ce bloc de code le fichier est ouvert en lecture, on peut l'utiliser normalement
print(fichier_ouvert.read())
# Ici, on est sorti du bloc et du contexte, le fichier à été fermé automatiquement
# Cette cellule génère une erreur
print(fichier_ouvert.read())
Exercice : Reprenez le code de l'exercice précédent, et utilisez
with
pour ne pas avoir à utiliser la méthodeclose()
.
# Votre code ici
Solution : exos/filewithfail.py
Il est possible de créer de nouveaux gestionnaires de contexte, pour que vos objets puissent être utilisés avec with
et que les ressources associées soient correctement libérées.
Pour plus d'informations sur la création de gestionnaires de contexte, voir ici.
Python a introduit une facilité d'écriture pour les listes qui permet de rendre le code plus lisible car plus concis.
# Ce code construit une liste ne contenant que les éléments pairs de la liste Liste1
Liste1 = list(range(10))
print(Liste1)
ListePaire = []
for i in Liste1:
if (i % 2) == 0:
ListePaire.append(i)
print(ListePaire)
# Ici, on fait la même chose, en liste...
ListePaire = [i for i in Liste1 if (i % 2) == 0]
print(ListePaire)
Cette concision peut être utile, mais n'en abusez pas, si vous commencez a avoir une compréhension de liste trop complexe a écrire en une simple ligne, faites le "normalement", avec les boucles et conditions explicites.
Plus d'informations ici.
C'est une forme d'écriture, très proche des compréhensions de listes, mais qui ne crée pas de nouvel objet liste immédiatement. Les items sont produits à la demande.
tuplePairs = (i for i in Liste1 if (i % 2) == 0)
print(tuplePairs)
print(list(tuplePairs))
Plus d'informations ici.
Python fournit un système de modularisation du code qui permet d'organiser un projet contenant de grandes quantités de code et de réutiliser et de partager ce code entre plusieurs applications.
L'instruction import
permet d'accéder à du code situé dans d'autres fichiers. Cela inclut les nombreux modules de la librairie standard, tout comme vos propres fichiers contenant du code.
Les fonctions et variables du module sont accessibles de la manière suivante :
<nom du module>.<nom de variable>
<nom du module>.<nom de fonction>([<parametre1>][, <parametre N>]...)
# Pour utiliser les fonctions mathématiques du module 'math'
import math
pi = math.pi
print('%.2f' % pi)
print('%.2f' % math.sin(pi))
Pour créer vos propres modules, il suffit de placer votre code dans un fichier avec l'extension '.py', et ensuite vous pourrez l'importer comme module dans le reste de votre code.
Il y a un fichier mon_module.py a coté du notebook, il contient du code définissant ma_variable
et ma_fonction()
.
import mon_module
print(mon_module.ma_variable)
mon_module.ma_fonction() # On accede ainsi à l'attribut ma_fonction() du module mon_module
On peut importer un module sous un autre nom (pour le raccourcir, en général) :
import mon_module as mm
mm.ma_fonction()
Note : un module n'est importé qu'une seule fois au sein d'une même instance Python.
Exercice : Modifiez le code contenu dans le fichier mon_module.py, et reexécutez la cellule ci-dessus.
Pour plus d'informations sur les modules, allez voir ici.
math
¶log()
sqrt()
cos()
pi
e
os
¶listdir()
getcwd()
getenv()
chdir()
environ()
os.path : exists(), getsize(), isdir(), join()
sys
¶argv
exit()
path
Mais bien plus sur la doc officielle de la stdlib !
Habituez-vous assez tôt aux conventions préconisées dans la communauté des utilisateurs de python. Cela vous aidera a relire plus facilement le code écrit par d'autres, et aidera les autres (et vous-même !) à relire votre propore code. Collaborez !
Ces conventions sont décrites dans le document PEP n°8 (Python Enhancement Proposal). L'outil pep8 permet d'automatiser la vérification du respect de ces règles.
Exercice :
- Lisez le PEP8, et corrigez toutes les fautes commises dans ce notebook
- Envoyez le résultat à votre formateur
Un package est un répertoire qui contient des modules (fichiers .py
) et un fichier __init__.py
. Une arborescence de packages permet de les organiser de manière hiérarchique.
On peut accéder aux sous-packages avec la notation :
import <package1>.<subpackage1>[.<subsubpackage>]...
Pour plus d'informations sur la construction de packages, voir ici
C'est le futur, et incidemment aussi le présent voire même le passé...
print()
range()
vs xrange()
2to3.py, 3to2, python-modernize, futurize
pylint --py3k
module de compatibilité: six
Plus d'informations sur le wiki officiel.
import this
Ecrivez la fonction odds()
qui prend une liste de nombres, et qui retourne une liste ne contenant que les nombres impairs.
odds([1,2,3,4,5]) => [1,3,5]
def odds(numbers):
# Votre code ici
pass
Solution : exos/odds.py
Ecrivez les fonctions :
majuscules('azERtyUI')
-> 'AZERTYUI'
minuscules('azERtyUI')
-> 'azertyui'
inverse_casse('azERtyUI')
-> 'AZerTYui'
nom_propre('azERtyUI')
-> 'Azertyui'
# Votre code ici
Solution : exos/chaines.py
Les fonctions dites "récursives" sont des fonctions qui font appel à elles-même, en résolvant une partie plus petite du problème à chaque appel, jusqu'à avoir un cas trivial à résoudre.
Par exemple pour calculer : "la somme de tout les nombres de 0 jusqu'à x", on peut utiliser une fonction récursive:
La somme de tous les nombres de 0 à 10 est égale à 10 plus la somme de tous les nombres de 0 à 9, etc...
def sum_to(x):
if x == 0:
return 0
return x + sum_to(x - 1)
print(sum_to(9))
La fonction mathématique factorielle est similaire, mais calcule : "le produit de tout les nombres de 1 jusqu'à x".
def fact(x):
if x == 1:
return 1
return x * fact(x - 1)
print(fact(5), fact(9))
La fonction mathématique qui calcule la suite des nombres de Fibonacci, peut être décrite comme suit:
fibo(0) = 0
fibo(1) = 1
Et pour toutes les autres valeurs:
fibo(x) = fibo(x - 1) + fibo(x - 2)
Exercice : écrivez une fonction récursive
fibo(x)
qui renvoie le x-ième nombre de la suite de Fibonnaci.
def fibo(x):
# Votre code ici
pass
print(fibo(9))
Solution : exos/fibo.py
Le but de ce jeu est de déplacer la pile de disques de la première colonne à la dernière, en s'aidant de la colonne intermédiaire, en suivant ces règles simples:
Exemple de solution pour une pile de quatre disques :
Pour cet exercice, on va représenter les colonnes avec des listes :
source = [4,3,2,1]
interm = []
destin = []
Le but est de tout déplacer vers la destination :
# Cette cellule génère une erreur
assert (source, interm, destin) == ([], [], [4,3,2,1]), "Le résultat n'est pas correct"
Nous allons utiliser pour déplacer un disque d'une colonne à une autre, la fonction move(a, b)
:
# Ne pas modifier cette fonction, utilisez-la dans votre fonction hanoi()
def move(a, b):
if not a:
raise Exception('Interdit: la colonne source est vide !')
item = a.pop()
if b and item > b[-1]:
raise Exception('Interdit: le disque {} est trop grand pour la colonne destination: {} => {}'.format(item, a, b))
b.append(item)
print('Déplaçons {}: source={}, interm={}, destin={}'.format(item, source, interm, destin))
Exercice : écrivez une fonction récursive
hanoi(taille, col_src, col_tmp, col_dst)
qui va déplacer les disques de la colonnecol_src
à la colonnecol_dst
en utilisant la fonctionmove()
.
def hanoi(size, source, interm, destin):
# Votre code ici
pass
Pour vérifier son fonctionnement :
hanoi(len(source), source, interm, destin)
assert (source, interm, destin) == ([], [], [4,3,2,1]), "Le résultat n'est pas correct"
Solution : exos/hanoi.py