Vous pouvez me contacter via Facebook pour questions & suggestions :
Page Facebook relative à mon site
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".
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).
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".
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.
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".
Une méthode est une fonction spécifique à un objet.
Pour chaque classe d'objets il existe un certain nombre de méthodes.
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()).
Chaque classe propose des méthodes.
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.
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.
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.
>>> 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.
>>> 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"
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.
>>> 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 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 ?
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).
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" ...
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.
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).
>>> 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.
La fonction native la plus utilisée est la fonction print(). Il convient de maitriser son usage.
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.
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 >>>
>>> 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 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()".
>>> 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
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".
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.
>>> 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.
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.
>>> 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.
J'entend par "normale" une fonction qui exige un ou plusieurs arguments lors de son appel et retourne une valeur.
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 ..."
>>> 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".
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.
Quelle est la portée d'une variable définie dans une fonction ?
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 ...
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.
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.
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.
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.
Je reviendrai sur les fonctions au chapitre 12.