Signature d'une fonction¶
Les fonctions sont à la base de la programmation. À partir d'une certaine taille, sans fonction il est quasiment impossible d'écrire un programme compréhensible (on a déjà pu mesurer l'utilité de toutes les fonctions que l'on a utilisées).
Une fonction se caractérise par :
- son nom
- son ou ses arguments
- sa ou ses valeurs de retour
On appelle cela la signature de la fonction.
Du point de vue syntaxique, on utilise le mot clef def
pour définir une fonction et return
pour indiquer
ce qu'elle retourne :
def carre(x): # carre est le nom, x est l'arguement
return x*x # la valeur de retour est ce qui suit return, donc x*x ici
print(carre(5))
print(carre(1+2j))
25 (-3+4j)
Python étant un langage dynamique, il ne demande pas de préciser le type des arguments. Cela permet que notre fonction carre fonctionne avec différents types. D'autre langages dits statiques, comme C ou C++, doivent définir la fonction pour chaque type possible en argument. Heureusement ces langage permettent la surcharge des fonctions c.a.d. permettre de définir plusieurs fonctions avec le même nom tant que leur signature est différente.
Python impose que chaque fonction ait un nom différent cependant la surcharge de fonction est possible comme on le verra dans le cours sur les décorateurs. On verra aussi que les notions de classes et de bibliothèques font que cette contrainte est rarement un problème.
Voici une autre fonction qui ne prend pas d'argument et qui retourne plusieurs valeurs. Lorsqu'on utilise une telle fonction il est nécessaire de mettre les parenthèses, avec rien dedans, pour différencier la fonction d'une variable qui aurait le même nom (c'est autorisé).
def dos():
return 2, "deux", "two"
a,b,c = dos()
print(b)
x = dos()
print(x)
deux (2, 'deux', 'two')
La fonction suivante est plus impressionnante mais elle n'est aussi qu'une simple fonction.
def eratosthene(n):
'''
Le crible d'Eratosthène donne l'ensemble des nombres premiers inférieurs à une valeur.
'''
liste = list(range(2, n))
index = 0
nombre = liste[index]
while nombre**2 <= n:
for i in liste[index + 1: ]:
if i % nombre == 0:
liste.remove(i)
index += 1
nombre = liste[index]
return liste
eratosthene(50)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
Notons le commentaire entre '''
qui décrit la fonction. Les commentaires sont très importants et ne doivent pas être négligés, ils servent aux autres et ils vous servent lorsque vous revenez sur votre code.
Valeurs par défaut¶
Il est possible de choisir des valeurs par défaut pour une fonction. Elles seront retenues si on ne les donne pas à l'usage :
def affiche(a, b = "b", c = "c"): # les variables qui peuvent avoir une valeur par défaut
#sont obligatoirement les dernières
print(a,b,c)
affiche("Z")
affiche("Z","Y")
affiche("Z","Y","X")
affiche("Z",c="Q") # on peut indiquer explicitement quel argument a quelle valeur
affiche(b="M") # erreur, il manque a comme indiqué
Z b c Z Y c Z Y X Z b Q
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-4-bf88a272a66e> in <module>() 7 affiche("Z","Y","X") 8 affiche("Z",c="Q") # on peut indiquer explicitement quel argument a quelle valeur ----> 9 affiche(b="M") # erreur, il manque a comme indiqué TypeError: affiche() missing 1 required positional argument: 'a'
Fonctions récursives¶
- Bonjour dit la fée, je vais exausser tes trois voeux, quels sont-ils ?
- Alors... je désire parler couramment le Python, n'avoir que des élèves sages et... 3 voeux de plus.
C'est le principe de la récursivité, la fonction s'appelle elle même. Avec la récursivité l'écriture de la suite de Fibonnacci est très simple :
def fibonacci(n):
if (n == 0) or (n == 1) :
return 1
else :
return fibonnacci(n-1) + fibonnacci(n-2)
fibonacci(10)
89
Cette écriture est élégante et plus compacte. Elle a néanmoins deux inconvénients :
- le premier appel de la fonction, ne sera fermé que lorsque le dernier le sera. Cela veut dire qu'avec factoriel(100) on a, à un moment, 100 fonctions qui ont commencé et qui sont toujours ouvertes. Avec de très grand nombre, cela peut devenir un problème pour la machine.
- elle va calculer 2 fois fibonacci(n-2) et chaque terme inférieur
Problèmes pas gérés...¶
Notons que notre programme ne gère pas le cas où la valeur données est négative ou un réel non entier. C'est mal, il faut toujours essayer de penser à tous les cas tordus possibles. Tôt ou tard, ils arriveront.
Pour cela on utilise beaucoup les exceptions que l'on verra plus tard.
Exercice¶
Ecrire deux fois la fonction factoriel, avec et sans la récursivité
def
factoriel_r(5)
def
factoriel(5)
def factoriel_r(n) :
if n <= 1 :
return 1
else :
return n * factoriel_r(n-1)
factoriel_r(5)
def factoriel(n) :
res = 1
for i in range(2,n+1) :
res *= i
return res
factoriel(5)
{{ PreviousNext("03 - Tests et boucles.ipynb", "05 - Erreurs et exceptions.ipynb") }}