Un script Python est un fichier texte enregistré avec l'extension .py que l'on peut créer par exemple avec un simple éditeur de texte comme le bloc note de Windows. Mais il est plus pratique d'utiliser un éditeur adapté pour l'écriture de scripts, comme Notepad++, PyScripter, Geany ou Bluefish.
Le langage Python est multi-paradigme, c'est-à-dire qu'il admet plusieurs manières différentes de traiter les problèmes. Les structures de contrôle (branchement conditionnel, boucles) permettent une programmation impérative en enchainant des instructions. La définition de fonctions réduit les répétitions dans le code et ouvre le champ à la programmation fonctionnelle. Mais surtout Python offre un cadre clair pour découvrir la programmation orientée objet : la structure des objets modélisés (atome, opération comptable, grammaire linguistique, variété algébrique, génôme…) est transcrite directement dans le code, avec les propriétés, relations et opérations associées.
Toutes ces approches ne sont pas incompatibles et un script Python peut très bien commencer par une déclaration d'objets, utiliser le lambda-calcul et se terminer par un algorithme impératif.
Un script Python n'a pas besoin d'une en-tête a priori, mais il est utile d'indiquer sur la première ligne le chemin d'accès vers l'interpréteur lorsqu'il est connu, précédé du shebang #!. On peut même préciser la version de Python avec laquelle le script doit être exécuté.
Sur la deuxième ligne, il est important de spécifier la norme de codage utilisée pour la saisie du programme, surtout si on y emploie des caractères accentués, d'autres signes diacritiques ou des caractères plus exotiques encore (Unicode), selon les cas ISO-8859-1 ou UTF-8. Les deux premières lignes du programme pourront donc apparaitre comme suit :
#! /usr/bin/env python3# -*- coding: ISO-8859-1 -*-
Contrairement à beaucoup de langages de programmation, Python ne délimite pas l'intérieur d'une boucle ou d'un branchement conditionnel à l'aide de commandes comme begin et end, mais par une indentation du code (en général avec quatre espaces). Les deux-points et l'indentation sont indispensables.
# Exemple d'utilisation d'un branchement conditionnelfrom time import strftimeh = int(strftime('%H')) # formatage de l'heure couranteif h < 18:print("Bonjour !")elif h < 22:print("Bonsoir !")else:print("Bonne nuit !")# Exemple d'utilisation d'une boucle itérativefor k in range(10, 0, -1): # intervalle parcouru en décroissantprint("C'est dans %d an%s, je m'en irai," % (k, (k>1)*'s'))print("j'entends le loup et le renard danser...")else:print("C'est cette année que je m'en vais...")# Exemple d'utilisation d'une boucle conditionnellefrom random import randintwhile randint(1, 6) < 6:print("Raté.")else:print("Six !")
La boucle for peut parcourir n'importe quel itérateur, entre autres les listes, uplets, chaines de caractères, dictionnaires, ensembles.
Les commandes elif et else sont facultatives. En sortie de boucle, elles sont même a priori inutiles mais peuvent différencier la sortie normale (fin de parcours de l'itérateur ou négation de la condition de boucle) d'une sortie sur interruption ou exception.
En effet, les boucles for et while peuvent être interrompues par l'instruction break.
# Détection de la présence d'une lettre en 6 exemplairesoccurrences = {}for c in "Supercalifragilisticexpialidocious":if occurrences.has_key(c):occurrences[c] += 1if occurrences[c] == 6:print("La lettre %s apparait au moins 6 fois." % c)break # fin de la recherche, sortie de boucle# pas de else pour ce branchementelse: # nouvelle lettreoccurrences[c] = 1else: # fin du motprint("Pas de lettre en 6 exemplaires ou plus.")
L'instruction continue à l'intérieur d'une boucle permet de passer directement à l'étape suivante de la boucle. L'instruction pass correspond à une action vide mais peut être utile lorsque la syntaxe exige au moins une instruction.
Une fonction est une suite d'instructions qui peuvent être appliquées à plusieurs objets donnés en paramètres et renvoyer éventuellement un résultat. Les noms des variables désignant les paramètres peuvent coïncider avec des noms de variables extérieures à la fonction sans impact sur ces dernières. Mais lorsque des objets modifiables (listes, objets…) sont passés en paramètres, ils sont susceptibles d'être modifiés lors de l'exécution de la fonction, par effet de bord.
Il existe plusieurs manières de saisir une fonction. Les différentes formes sont plus ou moins adaptées selon les contextes.
# À la manière du lambda-calculadd = lambda x: lambda y: x+yf = add(4)print(f(3)) # affiche : 7# Définition de fonctiondef polynome(coeffs):def fpolynome(x):resultat = 0puissance = 1for c in coeffs:resultat += c*puissancepuissance *= xreturn resultatreturn fpolynomecube = polynome([0, 0, 0, 1])print(cube(2)) # affiche : 8def toutincremente(liste_nbs):for i in range(len(liste_nbs)):liste_nbs[i] += 1print(toutincremente([1, 2, 4])) # affiche : None# En effet, la fonction toutincremente ne renvoie rien.liste = [1, 2, 4]toutincremente(liste)print(liste) # affiche : [2, 3, 5]
La deuxième forme de définition des fonctions permet de donner des valeurs par défaut aux paramètres, à l'aide de l'opérateur =. Il est même possible d'indiquer par une annotation la signification de chaque argument et du résultat.
def segmente(chaine: "mot à découper", taille: "longueur des segments" = 1, reste: "il y en a un peu plus, je vous le mets ?" = True) -> "liste des segments":resultat = []i = 1segment = []for c in chaine:segment.append(c)if i == taille:resultat.append(''.join(segment))segment = []i = 1else:i += 1if segment and reste:resultat.append(''.join(segment))return resultatsegmente('la valse à mille temps', 3)# affiche ['la ', 'val', 'se ', 'à m', 'ill', 'e t', 'emp', 's']
pgcd(a, b)ppcm(a, b)est_palindrome(texte)syracuse(n)nunivoyelles(texte)GramSchmidt(u, v, w)Plutôt que de renvoyer une liste, une fonction peut constituer un générateur dont les valeurs sont calculées successivement à chaque appel.
def premiers():yield 2;liste = []n = 3while True:for p in liste:if n % p == 0:breakelif p*p > n:yield nliste.append(n)breakelse:yield nliste.append(n)n += 2def premier_suivant(seuil):for p in premiers():if p > seuil:return p
Les classes permettent de définir des types complexes en intégrant les opérations usuelles associées. Chaque fonction définie à l'intérieur de la classe est à utiliser comme une méthode (c'est le sens du mot-clé self). Certaines de ces fonctions (nommées avec deux caractères souligné de chaque côté) servent pour les opérateurs et les fonctions globales.
class Polynome:"""Une classe pour les polynômes"""def __init__(self, coeffs): # constructeurif coeffs:self.coeffs = list(coeffs)else:self.coeffs = []k = len(self.coeffs)for c in self.coeffs[::-1]:k -= 1if c:self.deg = kbreakelse:self.deg = float(-inf)def ev(self, x):"""Évaluation en un scalaire."""resultat = 0puissance = 1for c in self.coeffs:resultat += c*puissancepuissance *= xreturn resultatdef __repr__(self, indeterminee = 'X'): # pour fonction printreturn ''.join([(' + ' if c > 0 else ' - ')+ (str(abs(c)) if k == 0else (('' if abs(c) == 1 else str(abs(c)))+ indeterminee + ('^' + str(k) if k > 1 else '')))for (k,c) in list(zip(range(self.deg+1),self.coeffs))[::-1]if c]).strip(' +')def __add__(self, other): # pour opérateur +coeffs = [a+b for (a, b) in zip(self.coeffs, other.coeffs)]if self.deg > other.deg:coeffs += self.coeffs[len(other.coeffs)-1:self.deg+2]else:coeffs += other.coeffs[len(self.coeffs)-1:other.deg+2]return Polynome(coeffs)def derive(self):"""Construction du polynome dérivé."""k = 0coeffs = []for c in self.coeffs[1:]:k += 1coeffs.append(k*c)return Polynome(coeffs)P = Polynome([4, 3, -0.5, 0, 2])print(P.derive()) # affiche 8X^3 - X + 3
Atome avec les champs symbole, Z (numéro atomique), valence, puis construire quelques atomes.Repere avec des champs précisant une position et une orientation dans l'espace, puis définir les fonctions de mouvement avant, lacet, roulis et tangage.Les exceptions permettent de gérer les erreurs d'exécution (mais pas les erreurs de syntaxe !) en renvoyant un code d'erreur qui pourra être traité à un niveau supérieur.
import mathdef sinc(x):try:return math.sin(x)/xexcept ZeroDivisionError:return 1def moyenne(liste):if len(liste)==0:raise NameError('Liste vide')return sum(liste)/len(liste)