- Langages et programmation -
Modularité
L’un des points forts de Python est sa licence libre et la possibilité offerte de créer des modules (bibliothèques) facilement.
A ce titre, Anaconda est une distribution Python contenant : * la bibliothèque standart * des logiciels d’édition (Spyder, Visual Studio Code…) * des terminaux (anaconda prompt qui implémente une invite de commande Windows, anaconda powershell) * de nombreux modules additionnels (dont les modules Jupyter)
Il est possible en une instruction de lister tous modules installés sur une machine :
# packages in environment at C:\ProgramData\Anaconda3:
#
# Name Version Build Channel
_ipyw_jlab_nb_ext_conf 0.1.0 py37_0
absl-py 0.8.1 pypi_0 pypi
alabaster 0.7.12 py37_0
anaconda 2019.03 py37_0
...
zstd 1.3.7 h508b16e_0
Note: you may need to restart the kernel to use updated packages.
La façon la plus simple et “propre” d’installer un module Python est de passer par une invite de commande.
Remarque : selon la machine il peut être nécessaire d’avoir ouvert l’invite de commande en administrateur.
Imaginons que l’on souhaite installer le module Pandas (utile pour les traitements de données type csv). Plusieurs solutions s’offrent à nous :
Anaconda est installé, on ouvre anaconda prompt et on tape conda install pandas
Python est installé, on ouvre une invite de commande et on tape pip install pandas
Python est installé mais pip
n’est pas reconnu par l’OS, seul python l’est. On tape python -m pip install panda
dans une invite de commande
Il existe deux façon d’utiliser un module dans un programme python :
import <nom_du_module>
: permet d’indiquer que l’on utilisera les fonctions du module indiqué. Chaque référence à une fonction se fera sous la forme <nom_du_module>.<fonction>
Par exemple :
3.0
from <nom_du_module> import <fonction>
: permet d’indiquer que l’on utilisera la fonction indiquée du module indiqué. Chaque référence à cette fonction se fera sous la forme <fonction>
Par exemple :
3.0
Cette deuxième façon de faire permet aussi d’importer l’ensembles des fonctions d’un module en une seule ligne :
1.0
Il est possible d’indiquer plusieurs modules ou fonctions à la fois :
3.3166247903554
3.0
Dans les cas de bases, la seconde méthode est plus facile : si l’on a besoin de choisir un entier aléatoire entre 1 et 6, on n’importe que la fonction randint
du module random
:
4
On peut même tout importer mais on ne sait pas exactement ce que l’on fait :
4
Quand le code commence à prendre de l’envergure, en projet par exemple, il est intéressant de garder la trace de l’origine de chaque fonction.
En effet dans certains cas, deux modules peuvent contenir une fonction portant le même nom : quelle fonction est alors utilisée ?
1
Help on built-in function randint:
randint(...) method of mtrand.RandomState instance
randint(low, high=None, size=None, dtype='l')
Return random integers from `low` (inclusive) to `high` (exclusive).
Return random integers from the "discrete uniform" distribution of
the specified dtype in the "half-open" interval [`low`, `high`). If
`high` is None (the default), then results are from [0, `low`).
Parameters
----------
low : int
Lowest (signed) integer to be drawn from the distribution (unless
``high=None``, in which case this parameter is one above the
*highest* such integer).
high : int, optional
If provided, one above the largest (signed) integer to be drawn
from the distribution (see above for behavior if ``high=None``).
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
single value is returned.
dtype : dtype, optional
Desired dtype of the result. All dtypes are determined by their
name, i.e., 'int64', 'int', etc, so byteorder is not available
and a specific precision may have different C types depending
on the platform. The default value is 'np.int'.
.. versionadded:: 1.11.0
Returns
-------
out : int or ndarray of ints
`size`-shaped array of random integers from the appropriate
distribution, or a single such random int if `size` not provided.
See Also
--------
random.random_integers : similar to `randint`, only for the closed
interval [`low`, `high`], and 1 is the lowest value if `high` is
omitted. In particular, this other one is the one to use to generate
uniformly distributed discrete non-integers.
Examples
--------
>>> np.random.randint(2, size=10)
array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0])
>>> np.random.randint(1, size=10)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Generate a 2 x 4 array of ints between 0 and 4, inclusive:
>>> np.random.randint(5, size=(2, 4))
array([[4, 0, 2, 1],
[3, 2, 2, 0]])
Help on method randint in module random:
randint(a, b) method of random.Random instance
Return random integer in range [a, b], including both end points.
Pour éviter les ambiguités, on importe alors seulement le module (quitte à utiliser un alias pour gagner en simplicité) :
Help on method randint in module random:
randint(a, b) method of random.Random instance
Return random integer in range [a, b], including both end points.
Help on built-in function randint:
randint(...) method of mtrand.RandomState instance
randint(low, high=None, size=None, dtype='l')
Return random integers from `low` (inclusive) to `high` (exclusive).
Return random integers from the "discrete uniform" distribution of
the specified dtype in the "half-open" interval [`low`, `high`). If
`high` is None (the default), then results are from [0, `low`).
Parameters
----------
low : int
Lowest (signed) integer to be drawn from the distribution (unless
``high=None``, in which case this parameter is one above the
*highest* such integer).
high : int, optional
If provided, one above the largest (signed) integer to be drawn
from the distribution (see above for behavior if ``high=None``).
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
single value is returned.
dtype : dtype, optional
Desired dtype of the result. All dtypes are determined by their
name, i.e., 'int64', 'int', etc, so byteorder is not available
and a specific precision may have different C types depending
on the platform. The default value is 'np.int'.
.. versionadded:: 1.11.0
Returns
-------
out : int or ndarray of ints
`size`-shaped array of random integers from the appropriate
distribution, or a single such random int if `size` not provided.
See Also
--------
random.random_integers : similar to `randint`, only for the closed
interval [`low`, `high`], and 1 is the lowest value if `high` is
omitted. In particular, this other one is the one to use to generate
uniformly distributed discrete non-integers.
Examples
--------
>>> np.random.randint(2, size=10)
array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0])
>>> np.random.randint(1, size=10)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Generate a 2 x 4 array of ints between 0 and 4, inclusive:
>>> np.random.randint(5, size=(2, 4))
array([[4, 0, 2, 1],
[3, 2, 2, 0]])
Un module python est en réalité un “simple” fichier contenant des fonctions à utiliser. Le plus souvent lors de l’importation, Python se contente de lire le fichier sans l’exécuter.
La création d’un module consiste donc essentiellement en la création de fonctions.
On peut avoir besoin de créer un module pour regrouper des objets (classes, fonctions, variables…) qui reserviront dans plusieurs codes ou afin d’alléger un code.
Dans ce cas, on doit coder correctement notre fonction (elle doit être correcte et ne pas bugger) et remplir une documentation.
Observons la définition de la fonction choice
de python : code source de python (ligne 296)
def choice(self, seq):
"""Choose a random element from a non-empty sequence."""
try:
i = self._randbelow(len(seq))
except ValueError:
raise IndexError('Cannot choose from an empty sequence') from None
return seq[i]
On observe : * une documentation entre les triples guillemets * une vérification que la liste est non vide. Un erreur est levée si c’est le cas * un retour
Il existe de nombreuses façons de rédiger des documentations.
Retenons qu’une bonne documentation doit avoir : * Une description générale de la fonction * Une description des arguments de la fonction (types, rôle) * Une description de la valeur retournée par la fonction
Par exemple :
def moyenne(tableau, colonne) :
"""
Fonction calculant la moyenne de la colonne indiquée du tableau fourni en argument
tableau est un tableau de tableaux. Chaque ligne contient différentes colonnes
colonne est le numéro de la colonne dont on veut calculer la moyenne
Renvoie la moyenne de la colonne concernée au format float
"""
# Préconditions (partielles)\n
assert isinstance(tableau, list), "tableau doit être une liste"
assert isinstance(colonne, int), "colonne doit être un entier"
somme = 0
for ligne in tableau :
somme += ligne[colonne]
return somme / len(tableau)
Lorsque l’on tape une fonction, on doit s’assurer de sa correction : * le fait que la fonction se termine (terminaison) … * … et qu’elle effectue les bons calculs sans créer d’erreur
Une façon de s’assurer que la fonction ne va pas créer d’erreur est de tester les arguments.
On peut utiliser différentes façon de faire dont le assert
:
assert <condition>, <Texte si la condition n'est pas respectée>
Voici un exemple pour la fonction racine_carrée
qui doit toujours manipuler des nombres, positifs de plus.
def racine_carrée(nombre) :
"""
Fonction calculant la racine carré du nombre fourni en argument
nombre est un nombre positif
Retourne la racine carré de nombre
"""
assert isinstance(nombre, (float, int)), "Le nombre doit être du type int ou float"
assert nombre >= 0, "Le nombre doit être positif"
from math import sqrt
return sqrt(nombre)
On peut alors tester notre fonction :
True
Et la gestion des erreurs :
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-3-5ae24efab6a4> in <module>
----> 1 racine_carrée(-9)
<ipython-input-2-b1b557790c3f> in racine_carrée(nombre)
5
6 # Préconditions à taper
----> 7 assert nombre >= 0, "Le nombre doit être positif"
8
9 from math import sqrt
AssertionError: Le nombre doit être positif