Accueil

Traduction

Tutoriel Python - sommaire

Tutoriel Python - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

Les fonctions en Python

La notion de fonction est omniprésente en Python. Dans ce chapitre vous verrez que Python vous propose un nombre impressionnant de fonctions prédéfinies (prêtes à l'emploi). Il existe les fonctions natives mais aussi les fonctions des modules ; les méthodes sont des fonctions spécifiques à une classe d'objets.

Dans ce chapitre je vous montre aussi comme produire et appeler vos propres fonctions.
Quid des variables déclarées dans une fonction perso ?
Je vous signale aussi dans ce chapitre l'importance du mot clé "global".

Les fonctions natives

Vous avez déjà utilisé de nombreuses fonctions natives de Python : print(), len(), type(), list(), etc.
Ci-desssous tableau de toutes les fonctions natives (ou génériques "built-in functions" en anglais) :

Ces fonctions sont toujours disponibles car définies dans le module de base de Python.
Ci-dessous une série de commandes pour vous familiariser avec certaines de ces fonctions.

>>> maliste =[7,3,5,1,9]
>>> max(maliste)
9
>>> min(maliste)
1
>>> sum(maliste)
25
>>> int(15.5)
15
>>> eval("15.5")
15.5
>>> pow(10,5)
100000
>>> round(17.89,1)
17.9
>>> abs(-10)
10
>>> machaine ="bonjour"
>>> max(machaine)
'u'
>>> min(machaine)
'b'

Ces fonctions sont dites aussi génériques car elles peuvent s'appliquer à différents types de données (à la différence des méthodes de classe qui sont spécifiques à un type d'objet.
Ainsi je vous montre que les fonctions min() & max() peuvent avoir pour argument une liste ou une chaine.
La fonction round(nombre décimal,n) arrondit à l'entier le plus proche OU au nombre de décimales si un deuxième argument est précisé.
La fonction pow(x,n ) élève x à la puissance n
eval(chaine numérique) : convertit une chaine en flottant à condition bien sûr que cette chaine ait un format numérique (suite de chiffres avec éventuellement un point décimal).

Les mots clés (ou mots réservés) en Python

Ne confondez pas les fonctions natives avec les mots clés.
La liste des mots clés peut être affichée dans la console :

>>> help("keywords")
Here is a list of the Python keywords.  Enter any keyword to get more help.

False               break               for                 not
None                class               from                or
True                continue            global              pass
__peg_parser__      def                 if                  raise
and                 del                 import              return
as                  elif                in                  try
assert              else                is                  while
async               except              lambda              with
await               finally             nonlocal            yield

Vous n'avez pas le droit d'utiliser un mot clé pour définir un identifiant (nom de variable simple, de fonction, de liste, ...).

>>> in = [5,4,3,2]
...
SyntaxError: invalid syntax
>>> del = (5,4,3)
...
SyntaxError: invalid syntax

On ne peut pas nommer une liste, un tuple avec le mot clé "in" ou "del".

Le mot clé "del"

del est un mot clé qui joue le rôle d'une fonction.

>>> liste =list(range(2,10))
>>> liste
[2, 3, 4, 5, 6, 7, 8, 9]
>>> del(liste[0])
>>> liste
[3, 4, 5, 6, 7, 8, 9]
>>> del(liste)
>>> liste
...
NameError: name 'liste' is not defined

J'ai supprimé le premier élément de la liste puis toute la liste avec le mot clé del donc la demande d'affichage de cette liste retourne un message d'erreur.

Compléments sur les fonctions natives de Python

Parmi les 72 fonctions natives certaines sont très utiles en mathématiques. Aussi faut-il les connaitre.
Par exemple, ne créez pas une fonction personnelle pour traiter la division entière ; elle existe déjà !

>>> ord('a')
97
>>> chr(97)
'a'
>>> bin(64)
'0b1000000'
>>> oct(64)
'0o100'
>>> hex(64)
'0x40'
>>> hex(192)
'0xc0'
>>> divmod(10,3)
(3, 1) # quotient et reste de la division de 10 par 3
>>> y =float("10000.55")
>>> y
10000.55

Attention pour les fonctions bin(),oct(), hex() les deux premièrs caractères de la réponse précisent la base : "0b" ou "0o" ou "0x".

Les méthodes

Une méthode est une fonction spécifique à un objet.
Pour chaque classe d'objets il existe un certain nombre de méthodes.

Exemple

Par exemple pour trier une liste, vous pouvez utiliser la fonction générique sorted() mais aussi la méthode de liste sort().
Commandes dans la console :

>>> maliste =[5,4,3,2,1]
>>> sorted(maliste)
[1, 2, 3, 4, 5]
>>> maliste
[5, 4, 3, 2, 1]
>>> maliste.sort()
>>> maliste
[1, 2, 3, 4, 5]
>>>

Pour utiliser une méthode, on a donc la syntaxe object.method(). C'est ce qu'on appelle la notation pointée. le point indiquant l'appartenance de la méthode à l'objet.
Dans le cas de la méthode sort() la liste est directement modifiée (ce qui n'est pas le cas avec la fonction générique sorted()).

Méthodes et classes d'objets

Chaque classe propose des méthodes.

Méthodes applicables à une instance de la classe 'list'

Astuce

Pour connaitre les méthodes applicables à un objet en fonction de son type, il suffit de taper la commande dir(nomClasse)

>>> dir(tuple)
...
 'count', 'index'
>>> dir (set)
...
 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection',
 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 
 'symmetric_difference', 'symmetric_difference_update', 'union', 'update'
>>>

Les tuples sont des séries non mutables donc les méthodes ne sont qu'au nombe de 2 alors que pour les ensembles la liste des méthodes disponibles est impressionnante.

Fonctions dans les modules

Il ne faut pas confondre vitesse et précipitation. Avant de vous lancer dans la création d'une fonction personnelle complexe, vous devez vous documenter sur les fonctions proposées par Python (qui ne limitent pas aux fonctions natives).

En plus des fonctions natives (celles dans le module de base), Python proposent des fonctions dans différents modules. Pour disposer de ces fonctions il faut donc importer le module en question.

Problématique

Je veux calculer la racine carré de 25. Je sais qu'il existe une fonction de Python qui fait ce travail : sqrt().

>>> sqrt(25)
...
NameError: name 'sqrt' is not defined

l'interpréteur me dit que la fonction sqrt() n'est pas définie ...
En effet cette fonction existe bien mais elle fait partie du module math, module qui n'a pas été importé donc elle n'est pas encore disponible.

Solution

>>> import math
>>> math.sqrt(25)
5.0
>>> math.ceil(18.9)
19
>>> math.floor(18.9)
18
>>>

Pour disposer de toutes les fonctions du module math il suffit de taper la commande import math qui importe la totalité du module : toutes les fonctions.
Ensuite pour appeler une fonction du module il faut la préfixer avec le nom du module.

Toutes les fonctions du module math

>>> dir(math)
'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh',
'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e',
 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 
'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 
'isfinite', 'isinf', 'isnan', 'isqrt', 'lcm',
'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter',
 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder',
'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc', 'ulp']
>>>

Il suffit de taper dir(math) pour obtenir la liste des fonctions proposées par ce module.
Vous devinez qu'il y a des fonctions de trigonométrie. J'aurais l'occasion d'y revenir ...
Il y a aussi une fonction nommée "factorial" et une autre nommée "gcd"

Le module random

Il existe un autre module qu'il faut souvent utiliser : random.
En anglais “random” signifie “le hasard”. Ce module propose des fonctions pour générer un réel, un entier de façon aléatoire, etc. Donc si vous voulez programmer des jeux simulant le hasard, ce module est incontournable.

Commandes à saisir dans l'interpéteur

>>> import random as rand
>>> alea = rand.random()
>>> alea
0.6545422177112703
>>> car_retenu = rand.choice(['a','b','c', 'd'])
>>> car_retenu
'c'
>>> entier = rand.randint(5,25)
>>> entier
8
>>>

J'ai utilisé trois fonctions du module random : random(),choice(), randint().
random() génère un réel entre 0 et 1 exclu.
choice() choisit une valeur dans une liste.
randint() génère un entier parmi un intervalle.

Les fonctions dans les bibliothèques

Les bibliothèques sont des extensions du langage Python.
Une bibliothèque comprend un ou plusieurs modules. Chaque module propose des fonctions.
À la différence des modules standards, les bibliothèques doivent être chargées (avec l'utilitaire PIP, par exemple).

Un seul exemple : pour tracer des courbes représentatives de fonctions, il faut disposer des fonctions du module pyplot. Ce module fait partie de l'extension matplolib. Il faudra au préalable télécharger sur votre PC cette extension.
Comment installer une extension ?

Ne pas "réinventer la roue"

Avant de vous lancer dans la création d'une fonction reposant sur un algorithme complexe, recherchez sur la "toile" pour savoir si elle n'existe pas en tant que fonction générique ou dans un module voire dans une bibliothèque.

Supposons que vous deviez calculer le plus grand commun diviseur de plusieurs nombres. Il suffit de saisir dans un moteur de recherche : python + plus grand commun diviseur
Le site "koor.fr" vous indique que la fonction se nomme "gcd" et est dans le module "math". Il est précisé aussi que cette fonction est récente : depuis Python 3.5

>>> import math
>>> math.gcd(14,35)
7
>>> math.gcd(60,50,40,30)
10

Il s'agit d'une fonction qui admet un nombre variable de paramètres (voir chapitre 12).

Mais au fait c'est quoi une fonction ?

J'ai employé de multiples fois le terme "fonction". J'ai évoqué les fonctions natives ainsi que les fonctions de module (module installé ou module d'extension). J'ai signalé que les méthodes étaient des formes particulières de fonctions.
Mais je n'ai pas encore défini le terme "fonction" ...

Définition

Une fonction est une portion de code nommée, qui accomplit une tâche spécifique. Les fonctions reçoivent généralement des données en entrée(arguments) et retournent généralement en sortie les résultats d'un traitement.

Paramètres et arguments

Définitions

Au propos des fonctions on emploie les termes paramètres et arguments

Les paramètres sont définis lors de la création de la fonction et servent de variables locales à l'intérieur de la fonction.
Les arguments sont les valeurs réelles passées à la fonction lors de son appel et doivent correspondre aux paramètres définis (ainsi deux arguments à saisir si deux paramètres obligatoires).

Exemple

>>> divmod(11,3)
(3, 2)
>>> q,r = divmod(11,3)
>>> q
3
>>> r
2
>>>

La fonction générique divmod (division entière) exige deux arguments lors de son appel et retourne deux valeurs. Elle a donc été définie avec deux paramètres.

À propos de la fonction print()

La fonction native la plus utilisée est la fonction print(). Il convient de maitriser son usage.

Un nombre variable d'arguments pour cette fonction

La fonction print() peut être argumentée avec plusieurs expressions (variables, chaines, numériques) séparées par une virgule. Par défaut chaque expression est séparée de la précédente avec un espace.

Le mot clé "sep"

Vous pouvez modifier le type de séparateur voir le supprimer avec le mot clé sep

>>> nom ='Marchand'
>>> prenom ='leon'
>>> age = 22
>>> print(nom, prenom, age, " ans")
Marchand leon 22  ans
>>> print(nom,prenom,age,' ans', sep ='-')
Marchand-leon-22- ans
>>> print(nom,prenom,age,'ans', sep ='')
Marchandleon22ans
>>>

Saut de ligne ou pas

>>> maliste = list(range(1,11,2))
>>> for ele in maliste :
...     print(ele)
...
1
3
5
7
9
>>> for ele in maliste :
...     print(ele,end ="-")
...
1-3-5-7-9->>>

Par défaut il y a un saut de ligne après l'instruction print() sauf si on emploie comme argument le mot clé end = ' '. Il faut préciser le type de séparateur dans les quotes.

Les chaines formatées (f-strings)

Les f-strings existent depuis la version 3.6 de Python. C'est un gros progrès en matière d'affichage de plusieurs expressions avec la même instruction "print()".

Un petit exemple vaut mieux qu'un long discours

>>> nom ="Dubuis"
>>> age = 22
>>> print(nom + " est âge de " + age + " ans")
...
TypeError: can only concatenate str (not "int") to str
>>> print(nom, "est âgé de :" , age, " ans")
Dubuis est âgé de : 22  ans
>>> print(f"{nom} est âgé de {age} ans")
Dubuis est âgé de 22 ans

Pourquoi les f-strings ?

L'instruction print(nom + " est âge de " + age + " ans") est fausse ! En effet la variable age n'est pas de type str.
La concaténation dans un "print()" peut s'avérer délicate. Plutôt que concaténer on aurait pu écrire : print(nom + " est âgé de : " + str(age) + " ans")
Mais cette dernière solution est lourde : délimiter chaque expression par une virgule, encadrer les chaines par des guillemets.

Préférez plutôt : print(f"{nom} est âgé de {age} ans")
Il s'agit alors d'une chaine formatée !

Une chaine formatée est délimitée par des guillemets doubles. et précédé de "f".
Dans une chaine formatée on peut insérer des variables de tout type à condition qu'elles soient entre accolades. C'est la notation "moustache".

Créez vos propres fonctions

Si vous n'avez pas trouvé votre bonheur (parmi les fonctions génériques, les fonctions des modules, les méthodes de classe, les fonctions dans les extensions) vous devez alors créer vos propres fonctions. Concrétement il faudra la définir puis l'appeler 1 ou N fois.
Pour définir une fonction personnelle il faut créer un bloc d'instructions commençant par le mot clé def.

Fonction sans paramètre et sans valeur retournée

>>> def date_courante():
...     import time
...     print("date du jour : " + time.strftime("%A %d %B %Y"))
...
>>> date_courante()  #appel de la fonction
date du jour : Wednesday 03 January 2024
>>>

Notez la syntaxe de la première ligne du bloc : def nomFonction(). Les parenthèses sont obligatoires.

La fonction "date_courante" n'exige aucun argument lors de son appel et se contente d'afficher la date du jour. Elle ne retourne aucune valeur.

Pour appeler la fonction il suffit d'écrire : nomFonction() donc aucun argument entre les parenthèses.
Mais la paire de parenthèses est obligatoire pour bien préciser que vous appelez une fonction.

Fonction avec paramètres mais sans valeur retournée

Ci-dessous je définis une fonction qui permet d'afficher une table de multiplication.
La fonction se contente d'afficher les données sous forme d'un tableau mais ne retourne rien à la routine principale.

>>> def table(nombre,ligne):
...     for i in range(1,ligne+1):
...             print(f" {i} * {nombre} = {i * nombre}")
...
>>> table(9,10)
 1 * 9 = 9
 2 * 9 = 18
 3 * 9 = 27
 4 * 9 = 36
 5 * 9 = 45
 6 * 9 = 54
 7 * 9 = 63
 8 * 9 = 72
 9 * 9 = 81
 10 * 9 = 90

Notez la syntaxe de la première ligne du bloc : def nomFonction(param1, param2)
La syntaxe de la commande "print()" est particulière ; J'y reviendrai plus tard.
Appel de la fonction : j'ai tapé table(9,10). Ce qui signifie que je demande l'affichage de la table par 9 et les dix premières lignes.

Fonction sans paramètre mais avec une valeur retournée

>>> def instant_present():
...     import time
...     return time.localtime()
...
>>> cejour = instant_present() 	#appel de la fonctionn
>>> print(cejour)
time.struct_time(tm_year=2024, tm_mon=12, tm_mday=29, tm_hour=9, tm_min=34, tm_sec=23, tm_wday=6, 
tm_yday=364, tm_isdst=0)

Notez le mot clé "return" qui signifie que la fonction retourne une (ou plusieurs) valeurs.
La valeur retournée est ici récupérée dans la variable "cejour".

Cette fonction perso est construite à partir de la fonction time.localtime() (fonction localtime du module time). Voir le chapitre 9 pour davantage d'explications.

Création de fonctions "classique"

J'entend par "normale" une fonction qui exige un ou plusieurs arguments lors de son appel et retourne une valeur.

La fonction parabole(x)

Cette fonction exige un argument lors de son appel et retourne valeur.

Création d'une fonction perso. basée sur l'équation : f(x) = x2 + 10 puis appel trois fois de cette fonction.

>>> def  parabole(x):
...     y = pow(x,2)+10
...     return y
...
>>> parabole(-10)
110
>>> parabole(0)
10
>>> parabole(10)
110

Dans la définition de parabole() je fais appel à une fonction native pow(n,e).
Ainsipow(x,2) élève à la puissance 2 le contenu de la variable x.
Le bloc d'instructions de cette fonction comprend deux lignes ; toutes deux doivent être indentées par rapport à la ligne "def ..."

Fonction qui retourne plusieurs valeurs

>>> def cercle(r):
...     aire = r * r * 3.14
...     circonference = r*2 * 3.14
...     return aire,circonference
...
>>> a,c = cercle(10)
>>> a
314.0
>>> c
62.8
>>>

La fonction nommmée "cercle" reçoit le rayon en argument et retourne la surface et la circonférence du cercle.
Appel de la fonction : a,c = cercle(10). L'aire du cercle de 10 de rayon est récupérée dans la variable "a" et la circonférence dans la variable "b".

Importance du mot clé "global"

En général une variable déclarée dans une fonction n'est manipulée qu'au sein de cette fonction et une variable déclarée en dehors de toute fonction n'est manipulée que dans le programme principal. Mais sinon le mot clé "global" devient utile.

Variable définie dans une fonction

Quelle est la portée d'une variable définie dans une fonction ?

Un script bogué

def cercle(r):
    pi =3.14
    aire = r * r * pi
    circon = r * 2 * pi
    return aire, circon

# appel de ma fonction perso
a,c = cercle(10)
print (a)
print (c)
print (pi)

Je veux afficher pi en dehors de la fonction. Or il s'agit d'une variable déclarée dans la fonction ...

Exécution dans le shell

314.0
62.800000000000004
...
NameError: name 'pi' is not defined

La dernière instruction plante !

Une variable déclarée dans une fonction est une variable locale.
Une variable locale est en effet créée lors de l'appel de la fonction mais détruite lorsque la fonction se termine.

Et si nous voulons à tout prix manipuler pi en dehors de la fonction ?

La solution ci-dessous :

def cercle(r):
    global pi
    pi =3.14
    aire = r * r * pi
    circon = r * 2 * pi
    return aire, circon

# appel fonction 
a,c = cercle(10)
print ("aire : ", a)
print ("circonference : ", c)
print ("valeur de pi : ", pi)

Règle : lorsqu'une variable est définie à l'intérieur d'une fonction, elle est considérée comme locale, sauf si elle est explicitement déclarée comme globale.

Le rendu dans le shell :

aire :  314.0
circonference :  62.800000000000004
valeur de pi :  3.14

Maintenant je peux appeler la variable pi n'importe où dans le script ; elle est devenue globale.

Variable globale et fonction

Appel d'une variable globale dans une fonction

Le script :

pi = 3.14
# ma fonction perso
def cercle(r):
    aire = r * r * pi
    circon = r * 2 * pi
    return aire, circon

# appel fonction 
a,c = cercle(10)
print ("aire : ", a)
print ("circonference : ", c)
print ("valeur de pi : ", pi)

La variable pi est déclarée en dehors d'une fonction ; elle est donc globale.

Le rendu :

aire :  314.0
circonference :  62.800000000000004
valeur de pi :  3.14

Je peux appeler une variable globale dans n'importe quelle fonction.

Modifier une variable globale dans une fonction

Le script bogué :

compteur = 0
# ma fonction perso
def iterations():
   compteur+=1
   return compteur

# appel fonction 
nbre_fois = iterations()
print(nbre_fois)

Je tente de modifier la variable globale compteur dans la fonction.

Le rendu :

...
UnboundLocalError: cannot access local variable 'compteur' where it is not associated with a value
...

Le programme "plante" !

La solulion :

compteur = 0
# ma fonction perso
def iterations():
    global compteur
    compteur+=1
    return compteur

# appel fonction 
nbre_fois = iterations()
print(nbre_fois)
nbre_fois = iterations()
print(nbre_fois)

Pour modifier une variable globale à l'intérieur d'une fonction, il est impératif de la déclarer avec le mot-clé global.

Le rendu :

1
2

Désormais la variable compteur est bien incrémentée.

Des fonctions plus complexes

Je reviendrai sur les fonctions au chapitre 12.

Fonctions complexes