# Programmation Python/Version imprimable2a

* Si vous imprimez cette page, choisissez « Aperçu avant impression » dans votre navigateur, ou cliquez sur le lien Version imprimable dans la boîte à outils, vous verrez cette page sans ce message, ni éléments de navigation sur la gauche ou en haut.
* Cliquez sur Rafraîchir cette page pour obtenir la dernière version du wikilivre.
* Pour plus d'informations sur les version imprimables, y compris la manière d'obtenir une version PDF, vous pouvez lire l'article Versions imprimables.
Une version à jour et éditable de ce livre est disponible sur Wikilivres, une bibliothèque de livres pédagogiques, à l'URL : https://fr.wikibooks.org/wiki/Programmation_Python

# Afficher un texte

Ce chapitre détaille les différentes manières d'afficher un texte en console, par exemple pour générer des logs. Les interfaces graphiques plus élaborées seront traitées avec des bibliothèques.

## print

La fonction print sert à afficher des données sur la sortie standard, qui est l’écran. Exemple :
La fonction help de l'interpréteur interactif donne la syntaxe des arguments de la fonction print :

### print formaté

Il est possible de changer une partie du texte en y incorporant des marqueurs de conversion précédés de l'opérateur "%". Il s'agit alors d'un "print formaté" (comme avec printf dans d'autres langages).
Les paramètres placés entre parenthèses à droite de la chaîne à afficher seront insérés dedans, en lieu et place des marqueurs. Cette technique a l'avantage de convertir automatiquement les variables pour qu'elles s'inscrivent dans le texte et qu'elles s'affichent.
Parmi les marqueurs disponibles, on trouve :
* %s représente un paramètre de type "string" (texte).
* %d un "digit" (nombre entier).
* %f un "floating" (flottant : nombre réel).
Exemple :
Depuis la 3.6, On peut aussi format de cette manière :
* f"{variable1} blabla {variable2} etc."
Donc en reprenant l'exemple au-dessus :
Cela équivaut à utiliser la méthode format :

### fstring

Similaire au print formaté, la syntaxe fstring est la suivante :

## input

la fonction input fait comme la fonction print, mais stoppe le programme en attente que l'utilisateur presse "entrée". Son résultat sera de type 'string' (chaîne de caractère, texte).
Ici le contenu de ce que l'utilisateur a tapé avant de valider sera stocké dans la variable nommée variable.

## raw_input

raw_input fait comme input, mais renvoie toujours une chaîne de caractère. Elle ne plante pas si le texte est vide.
À partir de Python 3.1, la fonction "raw_input" n'existe plus, et la fonction input la remplace et renvoie systématiquement une chaîne de caractères.

## Afficher des caractères spéciaux

Normalement, les symboles ne faisant pas partie du code ASCII sont traités comme les autres. Ex :
Toutefois selon l'encodage, il peut être nécessaire de les convertir en Unicode en plaçant un "u" avant :
Pour les retours à la ligne, utiliser "\n".

## Antislash

Les caractères affichés par les fonctions précédentes doivent être encadrés par des apostrophes ou des guillemets, mais que se passe-t-il s'ils contiennent eux-mêmes ces symboles ?
Testons la fonction print :
En Python, le simple quote peut encadrer le double, et le double peut encadrer le simple, car la chaîne commence au premier guillemet et finit au même guillemet.
Pour s'affranchir de ces limitations, on utilise un caractère d'échappement, qui est, en Python, l'antislash (« \ »). Il permet quelques subtilités complémentaires :
* En premier lieu, il permet d'écrire sur plusieurs lignes n'importe quel type de commande. Pratique pour éviter de dépasser les 120 caractères pouvant nécessiter l'utilisation d'un ascenseur latéral pour être lus.
* À l'intérieur d'une chaîne de caractères, l’antislash permet d'insérer un certain nombre de codes spéciaux (sauts à la ligne, apostrophes, guillemets, etc.). Exemples :
On remarque que la séquence \' permet d'insérer une apostrophe dans une chaîne délimitée par des apostrophes, et \" par des guillemets. De même, "\\" affiche "\".
D'autres caractères peuvent aussi être introduits par antislash :
* Retour chariot : \n
* Tabulation : \t

## Triple quotes

Si le nombre d’antislash nuit à la lisibilité du code, on peut délimiter la chaîne à l'aide de triples guillemets ou de triples apostrophes :

## Commentaires

Tout ce qui suit un dièse (#) jusqu'à un retour à la ligne est un commentaire : ce n'est pas pris en compte par l'interpréteur. Mais cette règle ne s'applique pas lorsque le dièse est positionné dans une chaîne de caractères (entre quotes).
Le but reste de produire du code compréhensible sans commentaire, mais ce texte affiché uniquement dans le code source, peut servir à expliquer à celui qui relit le code (y compris soi-même), les subtilités les moins évidentes de celui-ci.
* # Toute cette première ligne est un commentaire.
* print("Bonjour le monde") # Ceci est également un commentaire
* print("Bonjour"); print("Le monde"); # Ceci est une ligne comportant
* # plusieurs instructions
* print("Cette ligne ne contient pas de #commentaire")
* Exemple 1 : On notera que la fonction print affiche son argument.

### Commentaires de bloc

Les commentaires de bloc (block comments en anglais) permettent de commenter plusieurs lignes. En Python, ils sont assurés par des triples apostrophes ou guillemets :

## Couleurs

Il est possible d'écrire en couleurs dans un terminal ANSI (Linux) en précisant leurs codes. Exemple :

## Références

* ↑ https://docs.python.org/2.4/lib/typesseq-strings.html
* ↑ https://i.stack.imgur.com/6otvY.png

# Structure d'un programme
## Les instructions

Un programme Python est composé d'instructions. Une instruction est un ordre unitaire donné à un programme. Par exemple afficher Bonjour est une instruction, de même que calculer un plus un.
La structure d'un programme Python est certainement ce qui étonne le plus le programmeur ayant l'habitude d'un langage plus traditionnel comme le C : en Python les limites des instructions et des blocs sont définies par la mise en page.
* Le point-virgule (;) à la fin de chaque instruction est remplacé par le caractère de fin de ligne (symbolisé par "\n"). Ce qui simplifie la syntaxe car traditionnellement les points-virgules étaient toujours suivis de retours à la ligne.
* Les accolades () fréquemment utilisées pour définir les blocs sont remplacées par les niveaux d'indentations. En effet, il était déjà conseillé aux programmeurs de se servir aussi des sauts à la ligne et de l'indentation pour bien délimiter visuellement les blocs, donc c'est également un allègement du code.
En définitive, Python oblige à écrire du code lisible, et à prendre de bonnes habitudes conservables dans d'autres langages, ce qui en fait un langage idéal pour apprendre la programmation.

### Les espaces sont ignorés

À part ceux qui servent à l'indentation, en début de ligne, les espaces placés à l'intérieur des instructions sont ignorés, sauf s'ils font partie d'une chaîne de caractères.
L'interpréteur Python commence par analyser la première ligne :
* si celle-ci contient une instruction, alors il l'exécute
* si l'instruction n'est pas une instruction de contrôle, alors, il passe à la ligne suivante, l'analyse et l'exécute
* si le programme Python arrive à la fin du fichier à exécuter, alors, il sort du programme et en arrête l'exécution.
* print("Bonjour")
* 1+1
* c = 3e5
* e = m*c**2
* a, b, c = 1, 2, 3
* discriminant = b**2-4*a*c
* lambda x,y : x + y
* dico1 = {'prénom':'Eric', 'nom':'tartempion'}
* print ("Bonjour %s" % dico1['nom'])
* Exemple 1 : quelques instructions

## Notion de bloc d'instructions

Un bloc d'instructions est une suite d'instructions qui est alignée sur la même tabulation. Les blocs d'instructions sont créés par les instructions de contrôles comme if, while et for, ainsi que par les instructions permettant de déclarer des fonctions.
Sous Python, toutes les instructions composées ont toujours la même structure : une ligne d'en-tête terminée par un double point, suivie d'une ou de plusieurs instructions indentées sous cette ligne d'en-tête.
Il y a deux solutions pour indenter : utiliser quatre espaces ou un seul caractère tabulation, mais jamais un mélange des deux sous peine d'erreurs IndentationError: unindent does not match any outer indentation level. En effet, et même si le résultat paraît identique à l'écran, espaces et tabulations sont des codes binaires distincts : Python considérera donc que ces lignes indentées différemment font partie de blocs différents.
La tabulation est notamment la convention utilisée pour la librairie standard de Python, mais les espaces ont l'avantage de fonctionner avec tous les éditeurs (et ainsi, de pouvoir être plusieurs sur le même projet avec des éditeurs différents). On préférera donc se passer des tabulations : si vous utilisez un éditeur "intelligent", vous pouvez escamoter le problème en activant l'option "Remplacer les tabulations par des espaces", qui modifie ce que produit la touche tab.
S'il y a plusieurs instructions indentées sous la ligne d'en-tête, elles doivent l'être exactement au même niveau. Ces instructions indentées constituent ce que nous appellerons désormais un bloc d'instructions. Un bloc d'instructions est une suite d'instructions formant un ensemble logique, qui n'est exécuté que dans certaines conditions définies dans la ligne d'en-tête.
* #Ce bloc d'instruction est collé contre le bord gauche du fichier
* print("Je suis dans le premier bloc")
* print("Je suis toujours dans le premier bloc")
* if (a == 12) : #L'instruction ''if'' initie un nouveau bloc
* #Ce bloc est a quatre espace du bord
* print("Je suis dans le second bloc")
* print("Je suis encore dans le second bloc")
* if (b == 13 ) :
* #Il est possible d'imbriquer des blocs dans des blocs
* print("Je suis dans un troisième bloc")
* print("et ici aussi")
* print("Je reviens dans le second bloc")
* print("Je suis revenu(e) dans le premier bloc")
* Exemple 2 : Les blocs

# Variables
## Affectations

Une variable est un espace mémoire dans lequel il est possible de mettre une valeur. Par exemple, si en français je dis x est égal à 1, j'utilise la variable dont le nom est x pour lui fixer la valeur 1. Pour faire la même chose en Python, je note simplement : x = 1.
Cette opération est appelée "affectation" (ou "assignation"), et consiste à stocker une valeur en mémoire vive de l'ordinateur. On dit donc que l'on procède à l'affectation de la variable "x" avec la valeur "1".
En Python comme dans de nombreux autres langages, le symbole = est l'opérateur d'affectation. Cette valeur restera accessible jusqu'à la fin de l'exécution du programme (vérifiable avec "print(x)").
La valeur de la variable peut être un littéral, c'est-à-dire une constante, ou bien une expression (ex : une autre variable ou une instruction comme "1+1"). L'expression est évaluée avant d'être affectée à la variable.
En Python les constantes sont déclarées et affectées comme les variables. La convention PEP8 leur impose juste un nom en majuscules.
Ex :

### Réaffectation

Si la variable affectée n'existe pas, l'ordinateur la crée, sinon il écrase sa valeur. En effet, il est permis de ré-affecter une nouvelle valeur à une même variable, autant de fois qu'on le souhaite.
Ceci nous amène à attirer votre attention sur le fait que le symbole égale utilisé sous Python pour réaliser une affectation ne doit en aucun cas être confondu avec un symbole d'égalité tel qu'il est compris en mathématique. Il est tentant d'interpréter l'instruction altitude = 320 comme une affirmation d'égalité, mais ce n'en est pas une !
* Premièrement, l'égalité est commutative, alors que l'affectation ne l'est pas. Ainsi, en mathématique, les écritures a = 7 et 7 = a sont équivalentes, alors qu'une instruction de programmation telle que 375 = altitude serait illégale.
* Deuxièmement, l'égalité est permanente, alors que l'affectation peut être remplacée comme nous venons de le voir. Lorsqu'en mathématique, nous affirmons une égalité telle que a = b au début d'un raisonnement, alors a continue à être égal à b durant tout le développement qui suit.
En programmation, une première instruction d'affectation peut rendre égales les valeurs de deux variables, et une instruction ultérieure en changer ensuite l'une ou l'autre. Exemple :

### Affectations multiples

Sous Python, on peut assigner une valeur à plusieurs variables simultanément. Exemple d'affectation multiple :

### Affectations parallèles

On peut aussi effectuer des affectations parallèles à l'aide d'un seul opérateur :
Exercices
* Décrivez-le plus clairement et le plus complètement possible ce qui se passe à chacune des trois lignes de l'exemple ci-dessous : >>> largeur = 20 >>> hauteur = 5 * 9.3 >>> largeur * hauteur 930.0
* Assignez les valeurs respectives 3, 5, 7 à trois variables a, b, c. Effectuez l'opération a - b/c . Le résultat est-il mathématiquement correct ? Si ce n'est pas le cas, comment devez-vous procéder pour qu'il le soit ?
Solution1.
2.
Ou plus avancé avec un import afin de l'avoir sous forme de fraction :

## Principe de fonctionnement

L'essentiel du travail effectué par un programme d'ordinateur consiste à manipuler des données. Ces données peuvent être très diverses (tout ce qui est numérisable, en fait), mais dans la mémoire de l'ordinateur elles se ramènent toujours en définitive à une suite finie de nombres binaires.
Pour pouvoir accéder aux données, le programme d'ordinateur (quel que soit le langage dans lequel il est écrit) fait abondamment usage d'un grand nombre de variables de différents types.
Une variable apparaît dans un langage de programmation sous un nom de variable à peu près quelconque, mais pour l'ordinateur il s'agit d'une référence désignant une adresse mémoire, c'est-à-dire un emplacement précis dans la mémoire vive.
À cet emplacement est stocké une valeur bien déterminée. C'est la donnée proprement dite, qui est donc stockée sous la forme d'une suite de nombres binaires, mais qui n'est pas nécessairement un nombre aux yeux du langage de programmation utilisé. Cela peut être en fait à peu près n'importe quel « objet » susceptible d'être placé dans la mémoire d'un ordinateur, par exemple : un nombre entier, un nombre réel, un nombre complexe, un vecteur, une chaîne de caractères typographique, un tableau, une fonction, etc.

### Exemple

Prenons l'exemple suivant :
Les exemples ci-dessus illustrent des instructions d'affectation Python tout à fait classiques. Après qu'on les ait exécutées, il existe dans la mémoire de l'ordinateur, à des endroits différents :
* trois noms de variables, à savoir "n", "message" et "pi" ;
* trois séquences d'octets, où sont encodées le nombre entier "7", la chaîne de caractères "Quoi de neuf ?" et le nombre réel "3,14159".
Les trois instructions d'affectation ci-dessus ont eu pour effet chacune de réaliser plusieurs opérations dans la mémoire de l'ordinateur :
* créer et mémoriser un nom de variable ;
* lui attribuer un type bien déterminé ;
* créer et mémoriser une valeur particulière ;
* établir un lien (par un système interne de pointeurs) entre le nom de la variable et l'emplacement mémoire de la valeur correspondante.
On peut mieux se représenter tout cela par un diagramme d'état tel que celui-ci :
| n | message | pi |
| 7 | Quoi de neuf ? | 3.14159 |
Les trois noms de variables sont des références, mémorisées dans une zone particulière de la mémoire que l'on appelle espace de noms, alors que les valeurs correspondantes sont situées ailleurs, dans des emplacements parfois fort éloignés les uns des autres.

### Les références

Formellement, les variables Python sont des références, c'est à dire que écrire "a = ((1,0,0),(0,1,0),(0,0,1))" ne signifie pas que "a" vaut "((1,0,0),(0,1,0),(0,0,1))" mais que "a" référence le n-uplet "((1,0,0),(0,1,0),(0,0,1))". La différence est que ensuite, une autre variable peut référencer le même n-uplet, simplement avec "b = a". Si on modifie "b", alors "a" sera également modifié.
Notez que a et b ne sont pas "liés", ils référencent simplement le même objet.
Si ensuite on fait référence à un nouvel objet (par l'intermédiaire de l'opérateur d'affectation "="), b référencera toujours l'ancien objet, et une modification de l'un des objets ne modifiera pas l'autre.
Idem pour les nombres :

## Noms des variables

Les noms de variables sont des noms que vous choisissez vous-même assez librement. Efforcez-vous cependant de bien les choisir : de préférence assez courts, mais aussi explicites que possible, de manière à exprimer clairement ce que la variable est censée contenir. Par exemple, des noms de variables tels que "longitude" et "latitude" conviennent mieux que "x" et "y", car un bon programmeur doit veiller à ce que ses lignes d'instructions soient faciles à lire.
Sous Python, les noms de variables doivent en outre obéir à quelques règles simples :
* Un nom de variable est une séquence de lettres (a → z , A → Z) et de chiffres (0 → 9), qui doit toujours commencer par une lettre.
* La casse est significative (les caractères majuscules et minuscules sont distingués). Donc "Joseph", "joseph", et "JOSEPH" sont des variables différentes.
* les 29 « mots réservés » du langage sont déjà pris (ex : "print").
* Seules les lettres du code ASCII sont autorisées. Les lettres accentuées, les cédilles, les espaces, les caractères spéciaux tels que $, #, @, etc. sont interdits, à l'exception du caractère _ (souligné).
Il faut également noter que les variables dont le nom commence par le caractère _ ont une signification particulière :
* les noms commençant par un _ ne sont pas exportés lorsqu'ils se trouvent dans un module ;
* les noms commençant par deux _ et finissant par deux _ sont réservés par le langage lui-même, notamment pour la programmation orientée objet.
De plus, il est recommandé d'écrire les noms de variables avec une minuscule, car l'usage veut qu'on le réserve plutôt la majuscule aux noms de classes.
Si le nom d'une variable doit comporter plusieurs mots, il y a deux possibilités d'écrire le nom de la variable :
* En snake_case (à la C), c'est à dire en séparant les mots par le caractère "_". Exemple : marge_brut.
* En CamelCase (à la Java), c'est à dire en séparant les mots par un passage en haut de casse (lettre majuscule). Exemple : margeBrut.
Il convient aussi d'éviter autant que possible l'énumération de variables (toto1, toto2, toto3, ...), cela rend le programme parfaitement incompréhensible et sujet à des erreurs.
Il est possible de préfixer le nom de la variable par son type. Par exemple int_margeBrut, str_message_de_bienvenue, mais cela alourdit très fortement le programme. On pourra par exemple s'inspirer de la notation hongroise qui formalise ce mécanisme.
Sinon, d'autres notations existent ou peuvent être imposées en fonction d'un projet, des habitudes d'une entreprise, etc.

## Lister les variables

* Variables d'environnement :
* Variables globales :
* Variables locales :

# Opérateurs
## Définition

Un opérateur est un symbole (ou un mot réservé) utilisé pour effectuer une opération entre des opérandes.
Une opérande est une variable, un littéral ou bien une expression.
Une expression est une suite valide d'opérateurs et d'opérandes.
Par exemple, dans l'expression :
Il y a deux opérateurs ( = et +) et trois opérandes (x, y et 1).
Certains opérateurs peuvent avoir des comportements différents en fonction des types d'opérandes sur lesquels ils agissent : on parle alors de surcharge des opérateurs. Exemple :
* "+" additionne des nombres, mais concatène des chaînes de caractères.
* "*" multiplie des nombres entre eux, mais duplique des chaînes de caractères.
Il existe différentes catégories d'opérateur :

## Présentation des différents opérateurs
### les opérateurs d'affectation

* Affectation multiple, e.g. x = y = z = 3
* Affectation parallèle, e.g. x, y = 1 , 0.5
* Affectation avec opération : la variable est utilisée comme opérande de gauche et utilisée pour stocker le résultat :
    a = 5 a *= 2 # 10 a += 1 # 11 a /= 4 # 2.75
Depuis Python 3.8, l'opérateur morse réalise une affectation dans une expression.

### les opérateurs logiques

Les expressions avec un opérateur logique sont évaluées à 0 ou 1 pour chaque bit des opérandes entiers. Pour chaque bit des opérandes X et Y :
* X | Y : OU logique. Si le bit de X ou le bit de Y est évalué à 1, alors le bit résultant sera 1. Sinon, le bit résultant sera 0.
* X ^ Y : OU exclusif logique. Si le bit de X est différent du bit de Y, alors le bit résultant sera 1. Sinon, le bit résultant sera 0.
* X & Y : ET logique. Si le bit de X et le bit de Y sont tous les deux évalués à 1, alors le bit résultant sera 1. Sinon, le bit résultant sera 0.
* ~ X : NON logique. Le bit résultant est la valeur opposée du bit de X.

### les opérateurs booléens

Les expressions avec un opérateur booléen sont évaluées à True ou False.
* X or Y : OU booléen. Si X est évalué à True, alors l'expression est True et Y n'est pas évalué. Sinon, l'expression est évaluée à la valeur booléenne de Y.
* X and Y : ET booléen. Si X est évalué à False, alors l'expression est False et Y n'est pas évalué. Sinon, l'expression est évaluée à la valeur booléenne de Y.
* not X : NON booléen. Evalué à la valeur booléenne opposée de X.
En fait, ces opérateurs supportent n'importe quel type d'opérandes car ils sont convertis implicitement en valeur booléenne pour l'évaluation :
* Un entier est converti à False s'il vaut 0, et à True sinon ;
* Une chaîne de caractère, un tableau ou un dictionnaire est converti à False si elle / s'il est vide, et à True sinon. Il s'agit du même comportement que le précédent sur les entiers en utilisant le résultat de la fonction len donnant la taille sous la forme d'un entier.
Pour les opérateurs or et and avec des opérandes non-booléens, le comportement est donc le suivant
* X or Y : Retourne X si X équivaut à True, sinon retourne Y.
* X and Y : Retourne X si X équivaut à False, sinon retourne Y.

### les opérateurs de comparaisons

Tout comme les opérateurs logiques, les opérateurs de comparaison renvoient une valeur booléenne "True" ou "False". Les opérateurs de comparaisons s'appliquent sur tous les types de base.
* < strictement inférieur
* > strictement supérieur
* <= inférieur ou égal
* >= supérieur ou égal
* == égal
* != différent
* <> différent, on utilisera de préférence !=
* X is Y : X et Y représentent le même objet.
* X is not Y : X et Y ne représentent pas le même objet
Il est possible d'enchaîner les opérateurs : X < Y < Z, dans ce cas, c'est Y qui est pris en compte pour la comparaison avec Z et non pas l'évaluation de (X < Y) comme on pourrait s'y attendre dans d'autres langages.

### les opérateurs mathématiques

| symbole | opération | types | exemples |
| + | Addition | entier, réel chaîne de caractères | 6+4 == 10 "a" + "b"== "ab" |
| - | Soustraction | entier, réel | 6-4 == 2 |
| * | Multiplication | entier réel chaîne de caractères | 6*4 == 24 1.2 * 1 == 1.2 3 * "s" == "sss" |
| ** | Puissance | entier, réel | 12**2 == 144 |
| / | Division | entier réel | 6/4 == 1 (Python 2) 1.5 (Python 3) 6./4 == 1.5 |
| // | Division entière | entier, réel | 6//4 == 1 |
| % | Modulo | entier, réel | 6%4 == 2 |
La division entre deux entiers produit un entier en Python 2, et un nombre à virgule flottante en Python 3.
Comportement de la division entière et du modulo selon le signe des opérandes :
| >>> 7 // 4 1 >>> -7 // 4 -2 >>> 7 // -4 -2 >>> -7 // -4 1 | >>> 7 % 4 3 >>> -7 % 4 1 >>> 7 % -4 -1 >>> -7 % -4 -3 |

## Priorité des opérations

Lorsqu'il y a plus d'un opérateur dans une expression, l'ordre dans lequel les opérations doivent être effectuées dépend de règles de priorité. Sous Python, les règles de priorité sont les mêmes que celles qui vous ont été enseignées au cours de mathématique. Vous pouvez les mémoriser aisément à l'aide d'un « truc » mnémotechnique, l'acronyme PEMDAS :
* P pour parenthèses. Ce sont elles qui ont la plus haute priorité. Elles vous permettent donc de « forcer » l'évaluation d'une expression dans l'ordre que vous voulez. Ainsi 2*(3-1) = 4, et (1+1)**(5-2) = 8.
* E pour exposants. Les exposants sont évalués ensuite, avant les autres opérations. Ainsi 2**1+1 = 3 (et non 4), et 3*1**10 = 3 (et non 59049 !).
* M et D pour multiplication et division, qui ont la même priorité. Elles sont évaluées avant l'addition A et la soustraction S, lesquelles sont donc effectuées en dernier lieu. Ainsi 2-2*2 renvoie -2 et non 0 !Et 2+4/2 renvoie 4.0 et non 3.0 (Rappelez-vous que / est l'opérateur de la division décimale). Si deux opérateurs ont la même priorité, l'évaluation est effectuée de gauche à droite. Ainsi dans l'expression 59*100/60, la multiplication est effectuée en premier, et la machine doit donc ensuite effectuer 5900/60, ce qui donne 98.0.
* A et S pour addition et soustraction.
Dans le tableau ci-dessous :
* les opérateurs regroupés entre deux lignes épaisses ont la même priorité.
* le sens d'évaluation indique l'ordre d'évaluation des opérations dans une expression :
** → pour une évaluation de gauche à droite : a OP1 b OP2 c == (a OP1 b) OP2 c ;
** ← pour une évaluation de droite à gauche : a OP1 b OP2 c == a OP1 (b OP2 c).
* le type peut être :
** « groupe » pour un couple de caractères encadrant une ou plusieurs expressions,
** « binaire » pour un opérateur situé entre ses deux opérandes,
** « ternaire » pour un opérateur utilisant trois opérandes,
** « unaire » pour un opérateur précédant son unique opérande.
Précédence des opérateurs du plus au moins prioritaire :
| Symbole | Type | Évaluation | Nom |
| | Groupe | | Agencement de dictionnaire |
| | Groupe | | Agencement de n-uplet |
| | Groupe | | Agencement de liste |
| . | Binaire | → | Attribut |
| | Groupe | | Argument de fonction |
| | Groupe | | Partie (opérateur d'indiçage) |
| await | Unaire | ← | Attente de résultat |
| ** | Binaire | ← | Puissance |
| ~ | Unaire | ← | inversion de bit |
| + | Unaire | ← | Positif |
| - | Unaire | ← | Négatif |
| * | Binaire | → | Multiplier |
| @ | Binaire | → | Multiplication de matrices |
| / | Binaire | → | Diviser |
| // | Binaire | → | Résultat entier d'une division |
| % | Binaire | → | Modulo |
| + | Binaire | → | Addition |
| - | Binaire | → | Soustraction |
| << | Binaire | → | Décalage à gauche |
| >> | Binaire | → | Décalage à droite |
| & | Binaire | → | et logique |
| ^ | Binaire | → | ou exclusif |
| | | Binaire | → | ou logique |
| in | Binaire | → | Test d'appartenance |
| not in | Binaire | → | Test de non appartenance |
| is | Binaire | → | Test d'égalité type |
| is not | Binaire | → | Test de non égalité de type |
| < | Binaire | → | inférieur |
| > | Binaire | → | supérieur |
| <= | Binaire | → | inférieur ou égal |
| >= | Binaire | → | supérieur ou égal |
| == | Binaire | → | est égal |
| != | Binaire | → | est différent |
| not | Unaire | ← | non booléen |
| and | Binaire | → | et booléen |
| or | Binaire | → | ou booléen |
| if ... else ... | Ternaire | → | expression conditionnelle |
| lambda | Binaire | → | expression lambda |

## Opérateurs et expressions

On manipule les valeurs et les variables qui les référencent, en les combinant avec des opérateurs pour former des expressions. Exemple :
a, b = 7.3, 12 y = 3*a + b/5
Dans cet exemple, nous commençons par affecter aux variables "a" et "b" les valeurs "7,3" et "12". Python assigne automatiquement le type « réel » à la variable "a", et le type « entier » à la variable "b".
La seconde ligne de l'exemple consiste à affecter à une nouvelle variable "y" le résultat d'une expression qui combine les opérateurs "*", "+" et "/" avec les opérandes "a", "b", "3" et "5". Les opérateurs sont les symboles spéciaux utilisés pour représenter des opérations mathématiques simples, telles l'addition ou la multiplication. Les opérandes sont les valeurs combinées à l'aide des opérateurs.
Python évalue chaque expression qu'on lui soumet, aussi compliquée soit-elle, et le résultat de cette évaluation est toujours lui-même une valeur. À cette valeur, il attribue automatiquement un type, lequel dépend de ce qu'il y a dans l'expression. Dans l'exemple ci-dessus, la variable "y" sera du type réel, parce que l'expression évaluée pour déterminer sa valeur contient elle-même au moins un réel.
Les opérateurs Python ne sont pas seulement les quatre opérateurs mathématiques de base. Il faut leur ajouter l'opérateur "**" pour l'exponentiation, ainsi qu'un certain nombre d'opérateurs logiques, des opérateurs agissant sur les chaînes de caractères, des opérateurs effectuant des tests d'identité ou d'appartenance, etc.
Signalons au passage la disponibilité de l'opérateur modulo, représenté par le symbole "%". Cet opérateur fournit le reste de la division entière d'un nombre par un autre. Essayez par exemple :
Cet opérateur pourra être utile notamment pour tester si un nombre "a" est divisible par un nombre "b". Il suffira en effet de vérifier que "a % b" donne un résultat égal à zéro.
Exercices
* Testez les lignes d'instructions suivantes :
Solution On constate qu'une variable appartenant à l'ensemble des nombres entiers, multipliée par un nombre décimal, donne un décimal.

## Composition

Jusqu'ici nous avons examiné les différents éléments d'un langage de programmation, à savoir : les variables, les expressions et les instructions, mais sans traiter de la manière dont nous pouvons les combiner les unes avec les autres.
Or l'une des grandes forces d'un langage de programmation de haut niveau est qu'il permet de construire des instructions complexes par assemblage de fragments divers. Ainsi par exemple, si vous savez comment additionner deux nombres et comment afficher une valeur, vous pouvez combiner ces deux instructions en une seule :
Cela n'a l'air de rien, mais cette fonctionnalité qui paraît si évidente va vous permettre de programmer des algorithmes complexes de façon claire et concise. Exemple :
Attention :
Il y a une limite à ce que vous pouvez combiner ainsi. Le symbole pour l'égalité en mathématique est '='. Le symbole pour l'égalité en programmation Python est '=='
Ainsi par exemple,
* En mathématique : a + 1 = b ( '=' est symbole de l'égalité et ici on a une équation). m + 1 = b et a * x = b sont ici des équations mathématiques. Cette forme d’écriture est inutilisable pour modifier une variable en programmation.
* En programmation (Python et dans d'autres langages) : on peut écrire a = a + 1 ( '=' est l'opérateur d'affectation, symbole d'affectation). On affecte à la variable a, à gauche, un nouveau contenu. Cela signifie ici (en programmation uniquement) que la nouvelle valeur de a ( à gauche du signe d'affectation) va être remplacée par l'ancienne valeur de a ( à droite du signe d'affectation) incrémentée ici de la valeur 1. Avec a = a - 2 on décrémente la variable a de la valeur 2.
Nous aurons l'occasion de revenir bientôt sur ce sujet. Mais auparavant, il nous faut encore aborder un autre concept de grande importance.

## Références

* ↑ https://peps.python.org/pep-0008/#constants
* ↑ https://docs.python.org/fr/3.6/reference/expressions.html#operator-precedence

# Structures de contrôle
## Définition

Dans notre premier chapitre, nous avons vu que l'activité essentielle d'un analyste-programmeur est la résolution de problèmes. Or, pour résoudre un problème informatique, il faut toujours effectuer une série d'actions dans un certain ordre. La description structurée de ces actions et de l'ordre dans lequel il convient de les effectuer s'appelle un algorithme.
Les structures de contrôle sont les groupes d'instructions qui déterminent l'ordre dans lequel les actions sont effectuées. En programmation moderne, il en existe seulement trois :
* la séquence (ex : chaînes de caractères, tuples et listes) ;
* la sélection ;
* la répétition.

## Séquence d'instructions

Le « chemin » suivi par Python à travers un programme est appelé un flux d'instructions, et les constructions qui le modifient sont appelées des instructions de contrôle de flux.
Python exécute normalement les instructions de la première à la dernière, sauf lorsqu'il rencontre une instruction conditionnelle comme l'instruction "if". Une telle instruction va permettre au programme de suivre différents chemins suivant les circonstances.

## Sélection ou exécution conditionnelle

Si nous voulons pouvoir écrire des applications véritablement utiles, il nous faut des techniques permettant d'aiguiller le déroulement du programme dans différentes directions, en fonction des circonstances rencontrées. Pour ce faire, nous devons disposer d'instructions capables de tester une certaine condition et de modifier le comportement du programme en conséquence.
La plus simple de ces instructions conditionnelles est l'instruction "if", qui permet de tester une condition et de n'exécuter les instructions que si cette condition est vérifiée. Exemple :
En exécutant ce programme, on voit "a est plus grand que dix" apparaître à l'écran. On peut perfectionner le programme pour prendre en compte le cas ou "a" est plus petit que dix :
On utilise aussi parfois "elif" (contraction de "else if") :
L'expression entre parenthèses est ce que nous appellerons désormais une condition. L'instruction "if" permet de tester la validité de cette condition, une expression contenant un opérateur de comparaison. Si la condition est vraie, alors l'instruction que nous avons indentée après le « : » est exécutée. Si la condition est fausse, rien ne se passe. Notez que les parenthèses utilisées ici sont optionnelles sous Python. Nous les avons utilisées pour améliorer la lisibilité. Dans d'autres langages, il se peut qu'elles soient obligatoires.
Comme vous l'aurez certainement déjà compris, l'instruction "else" (« sinon », en anglais) permet de programmer une exécution alternative, dans laquelle le programme doit choisir entre deux possibilités. Mais on peut enchainer autant de conditions que nécessaires en utilisant avant l'instruction "elif" (contraction de « else if »).
Exemple :
Dans cet exemple, les deux lignes d'instructions indentées sous la ligne contenant l'instruction "if" constituent un même bloc logique : ces deux lignes ne sont exécutées - toutes les deux - que si la condition testée avec l'instruction "if" se révèle vraie, c'est-à-dire si le reste de la division de "a" par "2" est nul.

## Instructions imbriquées

Il est parfaitement possible d'imbriquer les unes dans les autres plusieurs instructions composées, de manière à réaliser des structures de décision complexes. Exemple :
Analysez cet exemple. Ce fragment de programme n'imprime la phrase « c'est peut-être un chat » que dans le cas où les quatre premières conditions testées sont vraies.
Pour que la phrase « c'est en tous cas un mammifère » soit affichée, il faut et il suffit que les deux premières conditions soient vraies. L'instruction d'affichage de cette phrase (ligne 6) se trouve en effet au même niveau d'indentation que l'instruction : if ordre == "carnivores": (ligne 3). Les deux font donc partie d'un même bloc, lequel est entièrement exécuté si les conditions testées aux lignes 1 & 2 sont vraies.
Pour que la phrase « c'est peut-être un canari » soit affichée, il faut que la variable embranchement contienne « vertébrés », et que la variable classe contienne « oiseaux ».
Quant à la phrase de la ligne 9, elle est affichée dans tous les cas, parce qu'elle fait partie du même bloc d'instructions que la ligne 1.

## pass

De manière générale, un bloc contient tout le code avec une même indentation.
Si à un endroit on a syntaxiquement besoin d'un bloc mais qu'il n'y a rien à faire, on peut utiliser l'instruction pass, qui justement ne fait rien.

# Instructions répétitives
## L'instruction "while"

Cette instruction est une boucle, c'est-à-dire qu'elle permet de répéter plusieurs fois un bloc d'instructions (en boucle).
"while" exécute des commandes tant qu'une ou plusieurs conditions sont vraies.
par exemple :
donne à l'exécution :
En effet, la seconde ligne indique à Python qu'il lui faut répéter continuellement le bloc d'instructions qui suit, tant que le contenu de la variable "a" reste inférieur à "5".
Comme l'instruction "if", l'instruction "while" amorce une instruction composée. Le double point à la fin de la ligne introduit le bloc d'instructions à répéter, lequel doit obligatoirement se trouver en retrait.
Nous avons ainsi construit notre première boucle de programmation, laquelle répète un certain nombre de fois le bloc d'instructions indentées. Voici comment cela fonctionne :
* Avec l'instruction "while", Python commence par évaluer la validité de la condition fournie entre parenthèses (celles-ci sont optionnelles, nous ne les avons utilisées que pour clarifier notre explication).
* Si la condition se révèle fausse, alors tout le bloc qui suit est ignoré et l'exécution du programme se termine.
* Si la condition est vraie, alors Python exécute tout le bloc d'instructions constituant le corps de la boucle, c'est-à-dire :
** l'instruction a = a + 1 qui incrémente d'une unité le contenu de la variable "a" (ce qui signifie que l'on affecte à la variable "a" une nouvelle valeur, qui est égale à la valeur précédente augmentée d'une unité).
** l'instruction "print" qui affiche la valeur courante de la variable "a".
* Lorsque ces deux instructions ont été exécutées, nous avons assisté à une première itération, et le programme boucle, c'est-à-dire que l'exécution reprend à la ligne contenant l'instruction "while". La condition qui s'y trouve est à nouveau évaluée, et ainsi de suite. Dans notre exemple, si la condition a < 5 est encore vraie, le corps de la boucle est exécuté une nouvelle fois et le bouclage se poursuit.

#### Remarques

* La variable évaluée dans la condition doit exister au préalable (il faut qu'on lui ait déjà affecté au moins une valeur).
* Si la condition est fausse au départ, le corps de la boucle n'est jamais exécuté.
* Si la condition reste toujours vraie, alors le corps de la boucle est répété indéfiniment (tout au moins tant que Python lui-même continue à fonctionner), en risquant de saturer les processeurs (si cela survient, presser CTRL + C pour annuler le lancement). Il faut donc veiller à ce que le corps de la boucle contienne au moins une instruction qui change la valeur d'une variable intervenant dans la condition évaluée par "while", de manière à ce que cette condition puisse devenir fausse et donc que la boucle se termine.
Exemple de boucle infinie (à éviter) :
Exemple : élaboration d'une table de multiplication.
On obtient donc la liste des carrés et des cubes des nombres de 1 à 12.

## Construction d'une suite mathématique

Le petit programme ci-dessous permet d'afficher les dix premiers termes d'une suite appelée « suite de Fibonacci ». Il s'agit d'une suite de nombres, dont chaque terme est égal à la somme des deux termes qui le précèdent. Analysez ce programme (qui utilise judicieusement l'affectation multiple). Décrivez le mieux possible le rôle de chacune des instructions.
Lorsque vous lancez l'exécution de ce programme, vous obtenez :
Les termes de la suite de Fibonacci sont affichés sur la même ligne. Vous obtenez ce résultat grâce à la virgule placée à la fin de la ligne qui contient l'instruction "print". Si vous supprimez cette virgule, les nombres seront affichés l'un en-dessous de l'autre.
Lorsque vous examinez un problème de cette nature, vous devez considérer les lignes d'instruction, bien entendu, mais surtout décortiquer les états successifs des différentes variables impliquées dans la boucle. Cela n'est pas toujours facile, loin de là. Pour vous aider à y voir plus clair, prenez la peine de dessiner sur papier une table d'états similaire à celle que nous reproduisons ci-dessous pour notre programme « suite de Fibonacci » :
| Variables | a | b | c |
| Valeurs initiales | 1 | 1 | 1 |
| Valeurs prises successivement, au cours des itérations | 1 2 3 5 … | 2 3 5 8 … | 2 3 4 5 … |
| Expression de remplacement | b | a+b | c+1 |
Dans une telle table, on effectue en quelque sorte « à la main » le travail de l'ordinateur, en indiquant ligne par ligne les valeurs que prendront chacune des variables au fur et à mesure des itérations successives. On commence par inscrire en haut du tableau les noms des variables concernées. Sur la ligne suivante, les valeurs initiales de ces variables (valeurs qu'elles possèdent avant le démarrage de la boucle). Enfin, tout en bas du tableau, les expressions utilisées dans la boucle pour modifier l'état de chaque variable à chaque itération.
On remplit alors quelques lignes correspondant aux premières itérations. Pour établir les valeurs d'une ligne, il suffit d'appliquer à celles de la ligne précédente, l'expression de remplacement qui se trouve en bas de chaque colonne. On vérifie ainsi que l'on obtient bien la suite recherchée. Si ce n'est pas le cas, il faut essayer d'autres expressions de remplacement.
Exercices
* Écrivez un programme qui affiche les 20 premiers termes de la table de multiplication par 7.
* Écrivez un programme qui affiche une table de conversion de sommes d'argent exprimées en euros, en dollars canadiens. La progression des sommes de la table sera « géométrique », comme dans l'exemple ci-dessous : 1 euro(s) = 1.65 dollar(s) 2 euro(s) = 3.30 dollar(s) 4 euro(s) = 6.60 dollar(s) 8 euro(s) = 13.20 dollar(s) etc. (S'arrêter à 16384 euros)
* Écrivez un programme qui affiche une suite de 12 nombres dont chaque terme soit égal au triple du terme précédent.
Solution
* >>> c = 0 >>> while c < 20: ... c = c +1 ... print c, "x 7 =", c*7 ou encore : >>> c = 1 >>> while c <= 20: ... print c, "x 7 =", c*7 ... c = c +1
* >>> s = 1 >>> while s <= 16384: ... print s, "euro(s) =", s *1.65, "dollar(s)" ... s = s *2
* >>> a, c = 1, 1 >>> while c < 13: ... print a, ... a, c = a *3, c+1
Exercices
* Ecrivez un programme qui calcule le volume d'un parallélépipède rectangle dont sont fournis au départ la largeur, la hauteur et la profondeur.
* Ecrivez un programme qui convertisse un nombre entier de secondes fourni au départ, en un nombre d'années, de mois, de jours, de minutes et de secondes. (Utilisez l'opérateur modulo : %).
* Ecrivez un programme qui affiche les 20 premiers termes de la table de multiplication par 7, en signalant au passage (à l'aide d'une astérisque) ceux qui sont des multiples de 3. Exemple : 7 14 21 * 28 35 42 * 49
* Ecrivez un programme qui calcule les 50 premiers termes de la table de multiplication par 13, mais n'affiche que ceux qui sont des multiples de 7.
* Ecrivez un programme qui affiche la suite de symboles suivante : * ** *** **** ***** ****** *******
Solution
* Réfléchissez !
* # Le nombre de secondes est fourni au départ : # (un grand nombre s'impose !) nsd = 12345678912 # Nombre de secondes dans une journée : nspj = 3600 * 24 # Nombre de secondes dans un an (soit 365 jours - # on ne tiendra pas compte des années bissextiles) : nspa = nspj * 365 # Nombre de secondes dans un mois (en admettant # pour chaque mois une durée identique de 30 jours) : nspm = nspj * 30 # Nombre d'années contenues dans la durée fournie : na = nsd / nspa # division <entière> nsr = nsd % nspa # n. de sec. restantes # Nombre de mois restants : nmo = nsr / nspm # division <entière> nsr = nsr % nspm # n. de sec. restantes # Nombre de jours restants : nj = nsr / nspj # division <entière> nsr = nsr % nspj # n. de sec. restantes # Nombre d'heures restantes : nh = nsr / 3600 # division <entière> nsr = nsr % 3600 # n. de sec. restantes # Nombre de minutes restantes : nmi = nsr /60 # division <entière> nsr = nsr % 60 # n. de sec. restantes print "Nombre de secondes à convertir :", nsd print "Cette durée correspond à", na, "années de 365 jours, plus" print nmo, "mois de 30 jours,", print nj, "jours,", print nh, "heures,", print nmi, "minutes et", print nsr, "secondes."
* # affichage des 20 premiers termes de la table par 7, # avec signalement des multiples de 3 : i = 1 # compteur : prendra successivement les valeurs de 1 à 20 while i < 21: # calcul du terme à afficher : t = i * 7 # affichage sans saut à la ligne (utilisation de la virgule) : print t, # ce terme est-il un multiple de 3 ? (utilisation de l'opérateur modulo) : if t % 3 == 0: print "*", # affichage d'une astérisque dans ce cas i = i + 1 # incrémentation du compteur dans tous les cas
* Réfléchissez !
* Réfléchissez !

## L'instruction "for"

La boucle "for" permet d'exécuter une itération un certain nombre de fois :
Pour le "foreach" (répétition pour chaque élément d'un itérable) :
Pour avoir les clés avec les valeurs :

## Les instructions "break", "continue"

L'instruction "break" permet d'arrêter une boucle avant sa fin. L'instruction "continue" est similaire, mais au lieu d'interrompre la boucle, elle permet de passer à l'itération suivante.
affichera
tandis que
affichera

# Types
## Typage des variables

Pour distinguer les uns des autres ces divers contenus possibles des variables, le langage de programmation fait usage de différents types de données (ex : le type 'entier', le type 'réel', le type 'chaîne de caractères', le type 'liste', etc.).
Python est un langage à typage dynamique. Cela signifie que bien que gérant différents types, lorsqu'une variable est affectée, l'interpréteur trouvera automatiquement son type sans que l'utilisateur soit contraint de le préciser. Ceci constitue une particularité intéressante de Python, qui le rattache à une famille particulière de langages où l'on trouve aussi par exemple Lisp, Scheme, et quelques autres.
Par opposition, le typage statique est préférable dans le cas des langages compilés comme C++ et Java, parce qu'il permet d'optimiser l'opération de compilation (dont le résultat est un code binaire « figé »). Dans ces langages, il faut toujours - par des instructions distinctes - d'abord déclarer (définir) le nom et le type des variables, et ensuite seulement leur assigner un contenu, lequel doit bien entendu être compatible avec le type déclaré.
Le typage dynamique quant à lui permet d'écrire plus aisément des constructions logiques de niveau élevé (métaprogrammation, réflexivité), en particulier dans le contexte de la programmation orientée objet (polymorphisme). Il facilite également l'utilisation de structures de données très riches telles que les listes et les dictionnaires.

## Types natifs

Liste des types :
| int | Nombre entier optimisé |
| long | Nombre entier de taille arbitraire |
| float | Nombre à virgule flottante |
| complex | Nombre complexe |
| str | Chaîne de caractère |
| unicode | Chaîne de caractère unicode |
| tuple | Liste de longueur fixe |
| list | Liste de longueur variable |
| dict | dictionnaire |
| file | Fichier |
| bool | Booléen |
| NoneType | Absence de type |
| NotImplementedType | Absence d'implementation |
| function | fonction |
| module | module |
Tableau des types Python 3.x ayant changé de nom depuis 2.x :
| nom | description | équivalent 2.x |
| int | nombre entier de longueur arbitraire | long |
| byte | chaîne de caractères ASCII | str |
| str | chaîne de caractères Unicode | unicode |

## Détermination d'un type

La fonction type permet de connaître le type d'une variable.
* >>> a=3
* >>> type(a)
* <type 'int'>
* Exemple 1 : utilisation de la fonction type

## Conversion des types

Il existe plusieurs fonctions qui permettent de forcer le type d'une variable en un autre type.
* bool : convertit en booléen : "0", "" et "None" donnent "False" et le reste "True".
* int : permet de modifier une variable en entier. Provoque une erreur si cela n'est pas possible.
* long : transforme une valeur en long.
* str : permet de transformer la plupart des variables d'un autre type en chaînes de caractère.
* float : permet la transformation en flottant.
* repr : similaire à "str". Voir la partie sur les objets
* eval : évalue le contenu de son argument comme si c'était du code Python.
* split : sépare une chaine en liste.
* join : transforme une liste en chaine, dont le séparateur est en préfixe (" ".join(MaListe)).
* datetime.strptime('20170727222900', '%Y%m%d%H%M%S') : change une chaine en date.
* maDate.strftime('%Y%m%d%H%M%S') : change une date en chaine.

# Numériques

Il existe deux types pour définir des nombres entiers : le type int et le type long. Il existe également un type pour représenter des nombres à virgule : le type float.

## Les nombres entiers de type int

Les int représentent le type le plus facilement représentable sur une architecture donnée. Par exemple, sur une machine 32-bits, la taille d'un int sera de 32-bit, donc un int permettra de représenter des nombres entre $-2^{31}$ et $2^{31}-1$, soit entre -2 147 483 648 et 2 147 483 647.
Un littéral int s'écrit tout simplement avec les chiffres de 0 à 9, précédé éventuellement du symbole -. Il est possible d'écrire ce littéral suivant trois bases :
* la base décimale : le littéral devra commencer par un chiffre entre 1 et 9
* la base octale (base 8) : le littéral devra commencer par 0 suivi de chiffres de 0 à 7
* la base hexadécimale (base 16): le littéral devra commencer par 0x suivi de chiffres de 0 à 9 et de lettres de A à F (en minuscule ou majuscule)
* x=1
* x=0
* x=-33
* x=4566
* x=2147483647
* x=076 #équivalent à x=62
* x=0xFF #équivalent à x=255
* x=0xa1 #équivalent à x=161
* Exemple 2 : Quelques entiers int'

## Les nombres entiers de type long

Un entier long est un entier dont la taille n'est limitée que par la mémoire allouée par l'ordinateur à l'interpréteur Python. C'est à dire qu'un long permet d'écrire des entiers aussi grands que l'on veut.
Il existe deux manières d'utiliser des long :
* il faut rajouter L ou l à la fin d'un littéral entier pour qu'il soit automatiquement long
* lorsque le résultat d'une opération dépasse la capacité de stockage d'un int, alors, ce résultat est automatiquement convertit en long
* x=1L
* x=-45l
* x=121212121212121212121212121 #Automatiquement converti en long
* x=2147483647+1
* Exemple 3 : Quelques entiers long'
Il n'est pas nécessaire d'utiliser le type long de manière systématique : pour les entiers de taille raisonnable, le type int est beaucoup plus optimisé.
Pour convertir un long en int (et inversement), il est possible d'utiliser les fonctions int et long.
* x = int(1L) #x est un int
* x = long(1) #x est un long
* x = int(12121212121212121) #x est quand même un long
* Exemple 4 : Utilisation des fonctions int et long

### Limite entre « integer » et « long »

Les lignes incluses dans le paragraphe d'une boucle while sont exécutées répétitivement, tant que sa condition est remplie.
Supposons que nous voulions modifier légèrement notre précédent exercice sur la suite de Fibonacci, de manière à obtenir l'affichage d'un plus grand nombre de termes. À priori, il suffit de modifier la condition de bouclage, dans la deuxième ligne. Avec while c<49:, nous devrions obtenir quarante-huit termes. Modifions donc légèrement l'exercice, de manière à afficher aussi le type de la variable principale :
Que pouvons-nous constater ?
Si nous n'avions pas utilisé la fonction type, qui nous permet de vérifier à chaque itération le type de la variable b, nous n'aurions rien remarqué du tout : la suite des nombres de Fibonacci s'affiche sans problème (et nous pourrions encore l'allonger de nombreux termes supplémentaires).
Il semble donc que Python soit capable de traiter des nombres entiers de taille illimitée.
L'exercice que nous venons de réaliser indique cependant qu'il se passe « quelque chose » lorsque ces nombres deviennent très grands. Au début du programme, les variables a, b et c sont définies implicitement comme étant du type integer. C'est ce qui se passe toujours avec Python lorsqu'on affecte une valeur entière à une variable, à condition que cette valeur ne soit pas trop grande. Dans la mémoire de l'ordinateur, ce type de donnée est en effet encodé sous la forme d'un bloc de 4 octets (ou 32 bits). Or la gamme de valeurs décimales qu'il est possible d'encoder sur 4 octets seulement s'étend de -2147483648 à + 2147483647 (Voir cours d'informatique générale).
Les calculs effectués avec ce type de variable sont toujours très rapides, parce que le processeur de l'ordinateur est capable de traiter directement par lui-même de tels nombres entiers à 32 bits. En revanche, lorsqu'il est question de traiter des nombres entiers plus grands, ou encore des nombres réels (nombres « à virgule flottante »), les logiciels que sont les interpréteurs et compilateurs doivent effectuer un gros travail de codage/décodage, afin de ne présenter en définitive au processeur que des opérations binaires sur des nombres entiers de 32 bits au maximum.
Vous savez déjà que le type des variables Python est défini de manière dynamique.
Puisqu'il s'agit du type le plus performant (aussi bien en termes de vitesse de calcul qu'en termes d'occupation de place dans la mémoire), Python utilise le type integer par défaut, chaque fois que cela est possible, c'est-à-dire tant que les valeurs traitées sont des entiers compris entre les limites déjà mentionnées plus haut (environ 2 milliards, en positif ou en négatif).
Lorsque les valeurs traitées sont des nombres entiers se situant au-delà de ces limites, leur encodage dans la mémoire de l'ordinateur devient plus complexe. Les variables auxquelles on affecte de tels nombres sont alors automatiquement définies comme appartenant au type « entier long » (lequel est désigné par long dans la terminologie Python).
Ce type long permet l'encodage de valeurs entières avec une précision quasi infinie : une valeur définie sous cette forme peut en effet posséder un nombre de chiffres significatifs quelconque, ce nombre n'étant limité que par la taille de la mémoire disponible sur l'ordinateur utilisé !
Exemple :
Dans l'exemple ci-dessus, la valeur des nombres affichés augmente très rapidement, car chacun d'eux est égal au produit des deux termes précédents.
Au départ, les variables a, b et c sont du type integer, puisqu'on leur affecte des petites valeurs numériques entières : 3, 2 et 1. À partir de la 8e itération, cependant, les variables b et a sont automatiquement converties l'une après l'autre dans le type long : le résultat de la multiplication des termes 6 et 7 est en effet déjà bien supérieur à la limite des 2 milliards évoquée plus haut.
La progression continue avec des nombres de plus en plus gigantesques, mais la vitesse de calcul diminue. Les nombres mémorisés sous le type long occupent une place variable dans la mémoire de l'ordinateur, en fonction de leur taille.

## Les nombres à virgule flottante (float)

Un nombre à virgule flottante est un nombre décimal qu'il est possible de représenter par sa mantisse et son exposant. Par exemple, le nombre 125,789 est représentable par le couple (mantisse = 1,25789, exposant = 2). La mantisse étant toujours comprise entre -10 et 10 exclus.
Les nombres sont traduits par la formule $nombre=mantisse*10^{exposant}$.
Les limites dépendent de l'architecture de la machine et sont équivalentes au type de donnée double du langage C.
Les littéraux peuvent s'écrire avec les chiffres, le caractère point pour indiquer la séparation entre la partie entière et la partie décimale et la lettre 'e' ou 'E' pour spécifier l'exposant.
* x = 1.234
* x = 1.0 #Notons qu'un entier peut être un flottant
* x = 1. #Même résultat que précédemment
* x = 1.234e54 #C'est à dire <math>1.234*10^{54}</math>
* x = 1.234E54 #idem
* x = -1.454e-2 #La mantisse et l'exposant peuvent être négatifs
* Exemple 5 : nombres à virgules
Essayons donc ce type de données dans un nouveau petit programme :
Comme vous l'aurez certainement bien compris, nous affichons cette fois encore une série dont les termes augmentent extrêmement vite, chacun d'eux étant égal au produit des deux précédents. Au huitième terme, nous dépassons déjà largement la capacité d'un integer. Au neuvième terme, Python passe automatiquement à la notation scientifique (« e+n » signifie en fait : « fois dix à l'exposant n »). Après le quinzième terme, nous assistons à nouveau à un dépassement de capacité (sans message d'erreur) : les nombres vraiment trop grands sont tout simplement notés « inf » (pour « infini »).
Le type float utilisé dans notre exemple permet de manipuler des nombres (positifs ou négatifs) compris entre 10e-308 et 10e+308 avec une précision de 12 chiffres significatifs. Ces nombres sont encodés d'une manière particulière sur 8 octets (64 bits) dans la mémoire de la machine : une partie du code correspond aux 12 chiffres significatifs, et une autre à l'ordre de grandeur (exposant de 10).
Exercices
* Écrivez un programme qui convertisse en radians un angle fourni au départ en degrés, minutes, secondes.
* Écrivez un programme qui convertisse en degrés, minutes, secondes un angle fourni au départ en radians.
* Écrivez un programme qui convertisse en degrés Celsius une température exprimée au départ en degrés Fahrenheit, ou l'inverse. La formule de conversion est : $T_{F}=T_{C}*1,8+32$
* Écrivez un programme qui calcule les intérêts accumulés chaque année pendant 20 ans, par capitalisation d'une somme de 100 euros placée en banque au taux fixe de 4,3 %
* Une légende de l'Inde ancienne raconte que le jeu d'échecs a été inventé par un vieux sage, que son roi voulut remercier en lui affirmant qu'il lui accorderait n'importe quel cadeau en récompense. Le vieux sage demanda qu'on lui fournisse simplement un peu de riz pour ses vieux jours, et plus précisément un nombre de grains de riz suffisant pour que l'on puisse en déposer 1 seul sur la première case du jeu qu'il venait d'inventer, deux sur la suivante, quatre sur la troisième, et ainsi de suite jusqu'à la 64e case. Écrivez un programme Python qui affiche le nombre de grains à déposer sur chacune des 64 cases du jeu. Calculez ce nombre de deux manières :
** le nombre exact de grains (nombre entier)
** le nombre de grains en notation scientifique (nombre réel)
Solution
* # Conversion degrés -> radians # Rappel : un angle de 1 radian est un angle qui correspond à une portion # de circonférence de longueur égale à celle du rayon. # Puisque la circonférence vaut 2 pi R, un angle de 1 radian correspond # à 360° / 2 pi , ou encore à 180° / pi # Angle fourni au départ en degrés, minutes, secondes : deg, min, sec = 32, 13, 49 # Conversion des secondes en une fraction de minute : # (le point décimal force la conversion du résultat en un nombre réel) fm = sec/60. # Conversion des minutes en une fraction de degré : fd = (min + fm)/60 # Valeur de l'angle en degrés "décimalisés" : ang = deg + fd # Valeur de pi : pi = 3.14159265359 # Valeur d'un radian en degrés : rad = 180 / pi # Conversion de l'angle en radians : arad = ang / rad # Affichage : print (deg, "°", min, "'", sec, '" =', arad, "radian(s)")
* Réfléchissez !
* # Conversion °Fahrenheit <-> °Celsius # A) Température fournie en °C : tempC = 25 # Conversion en °Fahrenheit : tempF = tempC * 1.8 + 32 # Affichage : print tempC, "°C =", tempF, "°F" # B) Température fournie en °F : tempF = 25 # Conversion en °Celsius : tempC = (tempF - 32) / 1.8 # Affichage : print (tempF, "°F =", tempC, "°C")
* Réfléchissez !
* >>> a, b = 1, 1 # variante : a, b = 1., 1 >>> while b<65: ... print (b, a) ... a,b = a*2, b+1 ...

## Les nombres complexes

Python est un des rares langages à proposer un type de base pour les nombres complexes $\mathbb {C}$. Un nombre complexe est un nombre composé d'une partie réelle et d'une partie imaginaire. On note $i$ une des racines du polynôme $x^{2}=-1$.
Dans certains contextes, (comme la physique), la racine de -1 est notée j. C'est ce qui se fait en Python.
Un littéral complexe s'écrit donc : a + bj, avec a et b des variables de type float. Attention, j doit être précédé d'un nombre car sinon, Python l'interprétera comme étant la variable j. Il ne doit pas y avoir d'espace entre ce nombre et j.
* x = 1 + 1j
* x = 1.2e3 + 1.5e7j
* x = 5j + 4
* x = 1 + x*1j
* Exemple 5 : quelques nombres complexes

# Booléens
## Définition

Un booléen est un type de données qui ne peut prendre que deux valeurs : vrai ou faux. En Python, les constantes littérales sont notées True et False.
Tous les types de variables peuvent être interprétés de manière booléenne. Par exemple, pour les entiers (int), la valeur "0" correspond à "faux" et les autres valeurs à "vrai". Il en est de même pour tous les autres types : une valeur particulière vaut False et le reste des valeurs True. Le tableau suivant présente les valeurs "faux" pour les principaux type de données.

## Exemple d'expressions booléennes

Affiche :
Que se passe-t-il ? Le programme consiste en un tas de print. Chaque print affiche un nombre et une expression. Le nombre sert à savoir de quel ligne on parle. Notez bien comme chaque expression finit soit par False ou True. En python False et True peuvent aussi être écrits 0 et 1.

### And

Voyez ce code :
Cela affiche respectivement a True et a False comme attendu, le premier est vrai, et le second est faux. La troisième ligne, print(3, a == 6 and b == 7), est un peu différente. L'opérateur and signifie que si les deux expressions qui l'entourent sont vraies alors toute l'expression l'est également, autrement elle est fausse. Le comportement de and peut être résumé comme suit :
| Expression | Résultat |
| True and True | True |
| True and False | False |
| False and True | False |
| False and False | False |
Notez que si la première expression est fausse Python ne vérifie pas la seconde car il sait que l'expression car il sait que tout l'expression est fausse. Essayez de lancer False and print("Salut") et comparez le à True and print("Salut"). Le terme technique pour ceci est short-circuit evaluation (littéralement "évaluation en circuit court").

### Not

La ligne suivante, print(5, not a == 7 and b == 7), utilise l'opérateur not. not retourne l'opposé d'une expression (l'expression pourrait être réécrite print(5, a != 7 and b == 7)). Voici la table de vérité :
| Expression | Résultat |
| not True | False |
| not False | True |

### Or

Les deux lignes suivantes, print(7, a == 7 or b == 7) et print(7, a == 7 or b == 6) utilisent l'opérateur or. or retourne vrai si la première expression est vraie ou si la seconde expression est vraie, si la seconde expression est vraie ou si les deux le sont. Si aucune n'est vraie il retourne faux. Voici sa table de vérité :
| Expression | Résultat |
| True or True | True |
| True or False | True |
| False or True | True |
| False or False | False |
Notez que si la première expression est vraie Python ne vérifie pas la seconde expression car il sait que toute l'expression est vraie. Cela marche car or est vrai si au moins une des expressions est vraie. La première partie est vraie donc la seconde pourrait être vraie ou fausse, mais l'expression est toujours vraie.
Les deux lignes suivantes, print(8, not (a == 7 and b == 6)) et print(9, not a == 7 and b == 6, montrent que les parenthèses peuvent être utilisées pour regrouper des expressions et forcer l’évaluation d'une partie en premier. Notez que les parenthèses ont changé l'expression de "faux" à "vrai". La raison est que les parenthèses ont forcé le not à s'appliquer à toute l'expression au lieu de seulement la partie a == 7.

### bool

La valeur booléenne d'une variable "x" peut être obtenue avec bool(x). Voici la table de vérité selon le type de la variable :
| Vrai | Faux |
| True | False |
| 1 | 0 |
| Nombre (positif ou négatif) | None |
| Chaine non vide | Chaine vide |
| Liste non vide | Liste vide |
| Dictionnaire non vide | Dictionnaire vide |
Pour tester si une variable "x" n'est pas nulle, on utilise : not x is None.

## Note sur les opérateurs booléens

x == ('a' or 'b') n'est pas équivalent à x == 'a' or x == 'b'. En effet, cela ne vérifie pas si x est équivalent aux caractères 'a' ou 'b', car l'expression booléenne s'arrête avant la fin par short-circuit evaluation.
Exemple :

## Véracité/fausseté d'une expression

Lorsqu'un programme contient des instructions telles que while ou if, l'ordinateur qui exécute ce programme doit évaluer la véracité d'une condition, c'est-à-dire déterminer si une expression est vraie ou fausse. Par exemple, une boucle initiée par while c<20: s'exécutera aussi longtemps que la condition c<20 restera vraie.
Mais comment un ordinateur peut-il déterminer si quelque chose est vrai ou faux ?
En fait - et vous le savez déjà - un ordinateur ne manipule strictement que des nombres. Tout ce qu'un ordinateur doit traiter doit d'abord toujours être converti en valeur numérique. Cela s'applique aussi à la notion de vrai/faux. En Python, tout comme en C, en Basic et en de nombreux autres langages de programmation, on considère que toute valeur numérique autre que zéro est « vraie ». Seule la valeur zéro est « fausse ». Exemple :
Le petit script ci-dessus n'affiche « faux » que si vous entrez la valeur 0. Pour toute autre valeur numérique, vous obtiendrez « vrai ».
Si vous entrez une chaîne de caractères ou une liste, vous obtiendrez encore « vrai ». Seules les chaînes ou les listes vides seront considérées comme « fausses ».
Tout ce qui précède signifie donc qu'une expression à évaluer, telle par exemple la condition a > 5 , est d'abord convertie par l'ordinateur en une valeur numérique. (Généralement 1 si l'expression est vraie, et zéro si l'expression est fausse). Exemple :
Le script ci-dessus vous renvoie une valeur b = 1 (condition vraie) si vous avez entré un nombre plus petit que 5.
Ces explications ne sont qu'une première information à propos d'un système de représentation des opérations logiques de l’algèbre de Boole.

## Exemple

Créer le fichier password1.py :
Resultats :
Exercices
Écrire un programme devine votre nom, avec seulement trois chances avant de terminer.
Solution

# Chaines de caractères
## Les données alphanumériques

Les chaînes de caractères ("string" en anglais) sont des listes de caractères. On parle de chaînage car les caractères se suivent et chaque caractère a sa place, comme les maillons d'une chaîne. Il est ainsi possible de faire apparaître plusieurs fois le même caractère dans une chaîne, afin de manipuler des phrases par exemple.
À la différence des données numériques, qui sont des entités singulières, les chaînes de caractères (ou string) constituent un type de donnée composite. Nous entendons par là une entité bien définie qui est faite elle-même d'un ensemble d'entités plus petites, en l'occurrence : les caractères. Suivant les circonstances, nous serons amenés à traiter une telle donnée composite, tantôt comme un seul objet, tantôt comme une suite ordonnée d'éléments. Dans ce dernier cas, nous souhaiterons probablement pouvoir accéder à chacun de ces éléments à titre individuel.
En fait, les chaînes de caractères font partie d'une catégorie d'objets Python que l'on appelle des séquences, et dont font partie aussi les listes et les tuples.

### Le type « string »

Sous Python, une donnée de type string est une suite quelconque de caractères délimitée soit par des apostrophes (simple quotes), soit par des guillemets (double quotes), soit par des triples quotes (''' ou """).
Exemples :
Résultat :
Les trois variables phrase1, phrase2, phrase3 sont donc des variables de type string.

## Accès aux caractères individuels d'une chaîne

Les chaînes de caractères constituent un cas particulier d'un type de données plus général que l'on appelle des données composites. Une donnée composite est une entité qui rassemble dans une seule structure un ensemble d'entités plus simples : dans le cas d'une chaîne de caractères, par exemple, ces entités plus simples sont évidemment les caractères eux-mêmes. En fonction des circonstances, nous souhaiterons traiter la chaîne de caractères, tantôt comme un seul objet, tantôt comme une collection de caractères distincts. Un langage de programmation tel que Python doit donc être pourvu de mécanismes qui permettent d'accéder séparément à chacun des caractères d'une chaîne.
Python considère qu'une chaîne de caractères est un objet de la catégorie des séquences, lesquelles sont des collections ordonnées d'éléments. Cela signifie simplement que les caractères d'une chaîne sont toujours disposés dans un certain ordre. Par conséquent, chaque caractère de la chaîne peut être désigné par sa place dans la séquence, à l'aide d'un index.
Pour accéder à un caractère bien déterminé, on utilise le nom de la variable qui contient la chaîne, et on lui accole entre deux crochets l'index numérique qui correspond à la position du caractère dans la chaîne.
Exemple :

## Taille des chaines

* Déterminer la longueur (c'est-à-dire le nombre de caractères) d'une chaîne, en faisant appel à la fonction intégrée len :

## Sous-chaines

L'opérateur d'indiçage () permet aussi de sélectionner des sous-chaines selon leurs indices. On appelle cette technique le slicing (« découpage en tranches »).
Dans la tranche [n,m], le n$^{ième}$ caractère est inclus, mais pas le m$^{ième}$. Si vous voulez mémoriser aisément ce mécanisme, il faut vous représenter que les indices pointent des emplacements situés entre les caractères, comme dans le schéma ci-dessous :
Au vu de ce schéma, il n'est pas difficile de comprendre que ch[3:7] extraira iett. Notez qu'il faut impérativement utiliser un deux-points (:) : l'utilisation d'une virgule ou d'un point-virgule retournera une erreur.
De plus, si la borne de départ est le premier caractère (indice 0) ou si celle d'arrivée est la dernière (indice égal à la longueur de la chaine), il devient facultatif. Une borne négative -x prendra le x-ième caractère en partant de la fin, ainsi -1 désignera le dernier caractère, -2 l'avant-dernier, -3 l’antépénultième, etc. Cela ne marche pas avec [-0], qui retournera le premier caractère car -0 = +0. Exemple :
Pour une chaîne de caractère chaine, les indices doivent être compris entre -len(chaine) et +len(chaine)-1. En dehors de cet intervalle, l'interpréteur retourne le message d'erreur suivant :
Pour vérifier le début et la fin d'une chaîne sans avoir à déterminer sur quelle longueur, on peut utiliser "startswith" et "endswith", mais c'est moins rapide car faisant appel à une fonction de plus haut niveau. $^{(Référencenécessaire)}$

## Concaténation

L'opération d'assembler plusieurs petites chaînes pour en construire une plus grande s'appelle concaténation et on la réalise sous Python à l'aide de l'opérateur "+". Exemple :
Pour convertir en nombre véritable une chaîne de caractères qui représente un nombre. Exemple :
Dans cet exemple, la fonction intégrée int convertit la chaîne en nombre entier, et str convertit l'entier en chaîne.

## Parcours d'une séquence : for... in...

Il arrive très souvent que l'on doive traiter l'intégralité d'une chaîne caractère par caractère, du premier jusqu'au dernier, pour effectuer à partir de chacun d'eux une opération quelconque. Nous appellerons cette opération un parcours. En nous limitant aux outils Python que nous connaissons déjà, nous pouvons envisager d'encoder un tel parcours sur la base de l'instruction while :
Cette boucle « parcourt » donc la chaîne nom pour en extraire un à un tous les caractères, lesquels sont ensuite imprimés avec interposition d'astérisques. Notez bien que la condition utilisée avec l'instruction while est index < len(nom), ce qui signifie que le bouclage doit s'effectuer jusqu'à ce que l'on soit arrivé à l'indice numéro 9 (la chaîne compte en effet 10 caractères). Nous aurons effectivement traité tous les caractères de la chaîne, puisque ceux-ci sont indicés de zéro à 9.
Le parcours d'une séquence est une opération très fréquente en programmation. Pour en faciliter l'écriture, Python vous propose une structure de boucle plus appropriée, basée sur le couple d'instructions for ... in ... :
Avec ces instructions, le programme ci-dessus devient :
Comme vous pouvez le constater, cette structure de boucle est plus compacte. Elle vous évite d'avoir à définir et à incrémenter une variable spécifique (un « compteur ») pour gérer l'indice du caractère que vous voulez traiter à chaque itération. La variable caract contiendra successivement tous les caractères de la chaîne, du premier jusqu'au dernier.
L'instruction for permet donc d'écrire des boucles, dans lesquelles l'itération traite successivement tous les éléments d'une séquence donnée. Dans l'exemple ci-dessus, la séquence était une chaîne de caractères. L'exemple ci-après démontre que l'on peut appliquer le même traitement aux listes :
L'exécution de ce script donne :
L'instruction for est un nouvel exemple d’instruction composée. N'oubliez donc pas le double point obligatoire à la fin de la ligne, et l'indentation du bloc d'instructions qui suit.
Le nom qui suit le mot réservé in est celui de la séquence qu'il faut traiter. Le nom qui suit le mot réservé for est celui que vous choisissez pour la variable destinée à contenir successivement tous les éléments de la séquence. Cette variable est définie automatiquement (c'est-à-dire qu'il est inutile de la définir au préalable), et son type est automatiquement adapté à celui de l'élément de la séquence qui est en cours de traitement.
Exemple :
L'exécution de ce script donne :
Bien que les éléments de la liste divers soient tous de types différents (une chaîne de caractères, un entier, un réel, une liste), on peut affecter successivement leurs contenus à la variable e, sans qu'il s'ensuive des erreurs (ceci est rendu possible grâce au typage dynamique des variables Python).
Exercices
* Écrivez un script qui détermine si une chaîne contient ou non le caractère « e ».
* Écrivez un script qui compte le nombre d'occurrences du caractère « e » dans une chaîne.
* Écrivez un script qui recopie une chaîne (dans une nouvelle variable), en insérant des astérisques entre les caractères. Ainsi par exemple, « gaston » devra devenir « g*a*s*t*o*n »
* Écrivez un script qui recopie une chaîne (dans une nouvelle variable) en l'inversant. Ainsi par exemple, « zorglub » deviendra « bulgroz ».
* En partant de l'exercice précédent, écrivez un script qui détermine si une chaîne de caractères donnée est un palindrome (c'est-à-dire une chaîne qui peut se lire indifféremment dans les deux sens), comme par exemple « radar » ou « s.o.s ».
Solution
* # Recherche d'un caractère particulier dans une chaîne # Chaîne fournie au départ : chain = "Monty python flying circus" # Caractère à rechercher : letter = "e" # Recherche proprement dite : i = 0 # indice du caractère en cours d'examen found = False # "drapeau" à lever si le caractère recherché est présent while i < len(chain): if chain[i] == letter: found = True i = i + 1 # Affichage : print(u"Le caractère", letter) # Le caractère e if found == 1: print(u"est présent") else: print(u"est introuvable") print(u"dans la chaîne", chain) # dans la chaîne Monty python flying circus
* Réfléchissez !
* # Insertion d'un caractère d'espacement dans une chaîne # Chaîne fournie au départ : ch = "Gaston" # Caractère à insérer : cr = "*" # Le nombre de caractères à insérer est inférieur d'une unité au # nombre de caractères de la chaîne. On traitera donc celle-ci à # partir de son second caractère (en omettant le premier). lc = len(ch) # nombre de caractères total i = 1 # indice du premier caractère à examiner (le second, en fait) nch = ch[0] # nouvelle chaîne à construire (contient déjà le premier caractère) while i < lc: nch = nch + cr + ch[i] i = i + 1 # Affichage : print(nch)
* # Inversion d'une chaîne de caractères # Chaîne fournie au départ : ch = "zorglub" lc = len(ch) # nombre de caractères total i = lc - 1 # le traitement commencera à partir du dernier caractère nch = "" # nouvelle chaîne à construire (vide au départ) while i >= 0: nch = nch + ch[i] i = i - 1 # Affichage : print(nch)
* Réfléchissez !
Exercices
* Dans un conte américain, huit petits canetons s'appellent respectivement : Jack, Kack, Lack, Mack, Nack, Oack, Pack et Qack. Écrivez un script qui génère tous ces noms à partir des deux chaînes suivantes : Si vous utilisez une instruction for... in... , votre script ne devrait comporter que deux lignes.
** prefixes = 'JKLMNOPQ'
** suffixe = 'ack'
* Rechercher le nombre de mots contenus dans une phrase donnée.
Solution
* prefixes, suffixe = "JKLMNOPQ", "ack" for p in prefixes: print p + suffixe
* # Comptage du nombre de mots dans "chain" chain = "Les petits ruisseaux font les grandes rivières" if len(chain) == 0: print(0) nm = 1 # la chaîne comporte au moins un mot for c in chain: if c == " ": # il suffit de compter les espaces nm = nm + 1 print(nm)

## Appartenance d'un élément à une séquence : if.. in...

L'instruction in peut être utilisée indépendamment de for, pour vérifier si un élément donné fait partie ou non d'une séquence. Vous pouvez par exemple vous servir de in pour vérifier si tel caractère alphabétique fait partie d'un groupe bien déterminé :
D'une manière similaire, vous pouvez vérifier l'appartenance d'un élément à une liste :
Cette instruction très puissante effectue donc à elle seule un véritable parcours de la séquence. À titre d'exercice, écrivez les instructions qui effectueraient le même travail à l'aide d'une boucle classique utilisant l'instruction while.
Exercices
* Écrivez un script qui affiche « vrai » si un caractère est un chiffre.
* Écrivez un script qui affiche « vrai » si un caractère est une majuscule.
Solution
* if character in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": print True else: print False

## Les chaînes sont des séquences non modifiables

Vous ne pouvez pas modifier le contenu d'une chaîne existante. En d'autres termes, vous ne pouvez pas utiliser l'opérateur dans la partie gauche d'une instruction d'affectation. Essayez par exemple d'exécuter le petit script suivant (qui cherche à remplacer une lettre dans une chaîne) :
Au lieu d'afficher « Bonjour à tous », ce script « lève » une erreur du genre : TypeError: object doesn't support item assignment. Cette erreur est provoquée à la deuxième ligne du script. On y essaie de remplacer une lettre par une autre dans la chaîne, mais cela n'est pas permis.
Par contre, le script ci-dessous fonctionne :
Dans cet autre exemple, en effet, nous ne modifions pas la chaîne "salut". Nous en recréons une nouvelle avec le même nom à la deuxième ligne du script (à partir d'un morceau de la précédente, soit, mais qu'importe : il s'agit bien d'une nouvelle chaîne).

## Les chaînes sont comparables

Tous les opérateurs de comparaison dont nous avons parlé à propos des instructions de contrôle de flux (c'est-à-dire les instructions if ... elif ... else) fonctionnent aussi avec les chaînes de caractères. Cela vous sera très utile pour trier des mots par ordre alphabétique :
Ces comparaisons sont possibles, parce que les caractères alphabétiques qui constituent une chaîne de caractères sont mémorisés dans la mémoire de l'ordinateur sous forme de nombres binaires dont la valeur est liée à la place qu'occupe le caractère dans l'alphabet. Dans le système de codage ASCII, par exemple, A=65, B=66, C=67, etc.

## Encodage

En python 2, pour encoder une chaîne en Unicode, il faut la préfixer par la lettre "u" :
En python 3, les chaînes de caractères sont en Unicode par défaut. Le préfixe u est donc facultatif. Il reste présent et utile si le programme doit pouvoir fonctionner à la fois en Python 2 et en Python 3.
Au sujet des chaînes de caractères, il est important de savoir que deux notions différentes de chaînes de caractères existent en Python.
Pour des raisons historiques dans les versions de Python inférieures à Python 2, on considérait une chaîne de caractère comme une chaîne d'octets. Ceci permettait d'avoir un seul type pour traiter de deux notions différentes, mais pouvait parfois engendrer de la confusion sur le type traité.
* Le type String contenait à la fois une séquence d'octet et une chaîne de caractères ASCII/UTF-8 (exemple : "Hello World").
Depuis la version 3 de Python, les types chaînes d'octet et chaîne de caractères sont clairement différenciées.
* Le type chaîne de caractères (classe str) contient des caractères Unicode (exemple: 'xyzzy', "frobozz")
* Les octets et tableaux d'octets (classes bytes et bytearray) ne contiennent que des octets (l'un est immutable alors que l'autre est mutable). Exemple : b'xyzzy'.
Pour résumer :
| Version de Python | Python 2 | Python 3 |
| Chaîne de caractères unicode | # Classe unicode s = u"abc" s # u'abc' s[1] # u"b" | # Classe str s = "abc" # ou s = u"abc" s # 'abc' s[1] # "b" |
| Chaîne d'octets | # Classe str s = "abc" s # 'abc' s[1] # "b" | # Classe bytes s = b"abc" s # b'abc' s[1] # 98 |
La différence de comportement est illustrée dans le tableau comparatif ci-dessous.
| Code | Résultat en Python 2 | Résultat en Python 3 |
| a = 'test' type(a) b = u'test' type(b) c = b'test' type(c) | str unicode str | str str bytes |
| a == b a == c b == c | True True True | True False False |

## Classement des caractères

Il est souvent utile de pouvoir déterminer si tel caractère extrait d'une chaîne est une lettre majuscule ou minuscule, ou plus généralement encore, de déterminer s'il s'agit bien d'une lettre, d'un chiffre, ou encore d'un autre caractère typographique.
Nous pouvons bien entendu écrire différentes fonctions pour assurer ces tâches. Une première possibilité consiste à utiliser l'instruction "in". Mais puisque nous savons désormais que les caractères forment une suite bien ordonnée dans le code ASCII, nous pouvons exploiter d'autres méthodes. Par exemple, pour déterminer si on a affaire à une minuscule :
Exercices
* Écrivez un script qui affiche « vrai » si l'argument transmis est un chiffre (avec une autre méthode que celles exploitées précédemment)
* Écrivez un script qui affiche « vrai » si un caractère est une majuscule
Solution
* if character >= "0" and character <= "9": print(True) else: print(False)
* if character >= "A" and character <= "Z": print(True) else: print(False)
Afin que vous puissiez effectuer plus aisément toutes sortes de traitements sur les caractères, Python met à votre disposition un certain nombre de fonctions prédéfinies :
* La fonction ord(character) accepte n'importe quel caractère comme argument. En retour, elle fournit le code ASCII correspondant à ce caractère. Ainsi ord('A') renvoie la valeur 65, et ord(u'é') 233.
* La fonction chr(number) fait exactement le contraire. L'argument qu'on lui transmet doit être un entier compris entre 0 et 255. En retour, on obtient le caractère ASCII correspondant. Ainsi chr(65) renvoie le caractère A.
Exercices
* Écrivez un petit script qui affiche une table des codes ASCII. Le programme doit afficher tous les caractères en regard des codes correspondants. À partir de cette table, établissez les relations numériques reliant chaque caractère majuscule à chaque caractère minuscule.
* À partir des relations trouvées, écrivez un script qui convertit tous les caractères d'une phrase donnée en capitales.
* À partir des mêmes relations, écrivez un script qui convertit tous les caractères d'une phrase en capitales.
* Écrivez un script qui compte le nombre de fois qu'apparaît tel caractère (fourni en argument) dans une phrase donnée.
* Écrivez un script qui affiche le nombre de voyelles contenues dans une phrase donnée.
Solution
* # Table des codes ASCII : c = 32 # Premier code ASCII <imprimable> while c < 128 : # caractères non accentués seulement print("Code"), c, ":", chr(c), " ", c = c + 1
* Réfléchissez !
* # Convertir majuscules -> minuscules et inversement : # Échange les majuscules et les minuscules de "chaine" chain = "Ferdinand-Charles de CAMARET" newChain = "" # chaîne à construire for car in chain: code = ord(car) if car >= "A" and car <= "Z": code = code + 32 elif car >= "a" and car <= "z": code = code - 32 newChain = newChain + chr(code) print(newChain)
* Réfléchissez !
* # Comptage de voyelles : # Teste si car est une voyelle" if character in "AEIOUYaeiouy": print(True) else: print(False) # Compte les voyelles présentes dans la chaîne "chaine" n = 0 for c in chaine: if voyelle(c): n = n + 1 print(n)

## Méthodes des objets string

Sous Python, les chaînes de caractères sont des objets. On peut donc effectuer de nombreux traitements dessus en utilisant des méthodes appropriées. En voici quelques-unes, choisies parmi les plus utiles. Mais vous pouvez obtenir la liste complète de toutes les méthodes associées à un objet à l'aide de la fonction intégrée dir('') ou help(str) :
* Les fonctions "str" et "repr" (pour représentation d'objet) permettent de transformer un objet Python quelconque en chaîne de caractères. Ces deux fonctions sont différentes : "str('chaine')" retournera 'chaine' tandis que "repr('chaine')" retournera "'chaine'".
* index(c) : retrouve l'index de la première occurrence du caractère "c" dans la chaîne, ou déclenche une erreur si absent (ValueError: substring not found).
* find(aiguille) : cherche la position d'une sous-chaîne aiguille dans la chaîne, en partant du début.
* rfind(aiguille) : pareil que "find" mais en partant de la fin (reverse).
<pre
* count(aiguille) : compte le nombre de sous-chaînes aiguille dans la chaîne.
* lower : convertit une chaîne en minuscules.
* upper : convertit une chaîne en majuscules.
* capitalize : convertit en majuscule la première lettre d'une chaîne.
* swapcase : convertit toutes les majuscules en minuscules et vice-versa.
* strip : enlève les espaces éventuels au début et à la fin de la chaîne (trime).
* replace(old, new) : remplace tous les caractères old par des caractères new dans la chaîne.
Dans la plupart de ces méthodes, il est possible de préciser quelle portion de la chaîne doit être traitée, en ajoutant des arguments supplémentaires.

## Références

* ↑ https://docs.python.org/2/tutorial/introduction.html#unicode-strings

# Listes
## Déclaration

Les listes sont des séquences, des collections ordonnées d'objets séparés par des virgules. On les déclare avec l'opérateur d'indiçage () :

## Lecture

Comme les caractères dans une chaîne, les objets placés dans une liste sont rendus accessibles par l'intermédiaire d'un index (un nombre qui indique l'emplacement de l'objet dans la séquence, à partir de zéro). De plus, le slicing (« découpage en tranches ») permet aussi de dégager une sous-liste en précisant deux index correspondant aux bornes de la plage.
Une sortie indicée donne :
Une séquence donne par slicing :

### Types

Les éléments qui constituent une liste peuvent être de types variés :
Dans cet exemple, en effet, les premiers éléments sont des chaînes de caractères, puis il y a un entier et un réel. À cet égard, le concept de liste est donc différent des tableaux (array) que l'on rencontre les langages de programmation de bas niveau, où tous les éléments doivent être du même type.

### Recherche

Vous pouvez aisément déterminer si un élément fait partie d'une liste à l'aide de l'instruction in :
Si l'emplacement de l'élément importe dans la liste :

## Modification
### Affectation

À la différence de ce qui se passe pour les chaînes, qui constituent un type de données non-modifiables, il est possible de changer les éléments individuels d'une liste :
Les exemples ci-dessus devraient attirer votre attention sur le fait qu'une tranche découpée dans une liste est toujours elle-même une liste (même s'il s'agit d'une tranche qui ne contient qu'un seul élément), alors qu'un élément isolé peut contenir n'importe quel type de donnée.
Exemple en deux dimensions :
Ainsi, dans l'exemple ci-dessus on remplace le premier élément d'une liste (n° 0), qui est elle-même l'élément n° 5 d'une autre liste.

### Opérations

On peut appliquer aux listes les opérateurs + (concaténation) et * (multiplication) :
L'opérateur * est particulièrement utile pour créer une liste de "n" éléments identiques :

### Techniques de slicing avancées pour modifier une liste
#### Insertion

Insertion d'un ou plusieurs éléments n'importe où dans une liste :
Pour utiliser cette technique, vous devez prendre en compte les particularités suivantes :
* Si vous utilisez l'opérateur [ ] à la gauche du signe égale pour effectuer une insertion ou une suppression d'élément(s) dans une liste, vous devez obligatoirement y indiquer une « tranche » dans la liste cible (c'est-à-dire deux index réunis par le symbole ":"), et non un élément isolé dans cette liste.
* L'élément que vous fournissez à la droite du signe égale doit lui-même être une liste. Si vous n'insérez qu'un seul élément, il vous faut donc le présenter entre crochets pour le transformer d'abord en une liste d'un seul élément. Notez bien que l'élément mots[1] n'est pas une liste (c'est la chaîne fromage), alors que l'élément mots[1:3] en est une.

#### Suppression

Suppression / remplacement d'éléments :
* À la première ligne de cet exemple, nous remplaçons la tranche [2:5] par une liste vide, ce qui correspond à un effacement.
* À la quatrième ligne, nous remplaçons une tranche par un seul élément. (Notez encore une fois que cet élément doit lui-même être « présenté » comme une liste).
* À la 7e ligne, nous remplaçons une tranche de deux éléments par une autre qui en comporte 3.

#### Différence

Pour obtenir la différence entre deux listes :

#### Intersection

Pour l'intersection entre deux listes (en préservant l'ordre des éléments y compris leurs doublons), on applique la différence de la différence :

### Copie

Considérons que vous disposez d'une liste fable que vous souhaitez recopier dans une nouvelle variable que vous appellerez phrase. La première idée qui vous viendra à l'esprit sera certainement d'écrire une simple affectation telle que :
En procédant ainsi, sachez que vous ne créez pas une véritable copie. À la suite de cette instruction, il n'existe toujours qu'une seule liste dans la mémoire de l'ordinateur. Ce que vous avez créé est seulement une nouvelle référence vers cette liste. Essayez par exemple :
Si la variable phrase contenait une véritable copie de la liste, cette copie serait indépendante de l'original et ne devrait donc pas pouvoir être modifiée par une instruction telle que celle de la troisième ligne, qui s'applique à la variable fable. Vous pouvez encore expérimenter d'autres modifications, soit au contenu de fable, soit au contenu de phrase. Dans tous les cas, vous constaterez que les modifications de l'une sont répercutées dans l'autre, et vice-versa.
En fait, les noms fable et phrase désignent tous deux un seul et même objet en mémoire. Pour décrire cette situation, les informaticiens diront que le nom phrase est un alias du nom fable.
Nous verrons plus tard l'utilité des alias. Pour l'instant, nous voudrions disposer d'une technique pour effectuer une véritable copie d'une liste. Avec les notions vues précédemment, vous devriez pouvoir en trouver une par vous-même.
Cette fonctionnalité vous permet d'améliorer la lisibilité de vos programmes. Exemple :

## Méthodes

Sous Python, les listes sont des objets à part entière, et vous pouvez donc leur appliquer un certain nombre de méthodes particulièrement efficaces, après l'opérateur "." :

### append

append (ajouter) : l'exemple suivant qui fait appel à la méthode "append" de l'objet "liste" (déclarée vide) illustre ce concept.
Il s'agit de remplir la hotte du Père Noël.

### split

split : convertit une chaîne en une liste de sous-chaînes. On peut choisir le caractère séparateur en le fournissant comme argument, sinon c'est un espace, par défaut.

### join

join(liste) : rassemble une liste de chaînes en une seule (Cette méthode fait donc l'inverse de la précédente). Attention : la chaîne à laquelle on applique cette méthode est celle qui servira de séparateur (un ou plusieurs caractères) ; l'argument transmis est la liste des chaînes à rassembler.

### pop

pop(i) retire et renvoie l'élément de la liste d'index i. Si i est vide, il traite le dernier élément.

## Fonctions
### len

La fonction intégrée len, que nous avons déjà rencontrée à propos des chaînes, s'applique aussi aux listes. Elle renvoie le nombre d'éléments présents dans la liste :
Supposons par exemple que vous voulez créer une liste B qui contienne le même nombre d'éléments qu'une autre liste A. Vous pouvez obtenir ce résultat de différentes manières, mais l'une des plus simples consistera à effectuer : B = [0]*len(A).

### del

Une autre fonction intégrée permet de supprimer d'une liste un élément ou plusieurs éléments quelconques à partir de leurs index. Il s'agit de la fonction del :

### min et max

* min(liste) : minimum d'une liste (élément ayant la plus petite valeur).
* max(liste) : maximum d'une liste.

### range

Si vous devez manipuler des séquences de nombres, vous pouvez les créer très aisément à l'aide de cette fonction :
Sous python 3.6: print(list(range(10))) La fonction range génère une liste de nombres entiers de valeurs croissantes. Si vous appelez range avec un seul argument, la liste contiendra un nombre de valeurs égal à l'argument fourni, mais en commençant à partir de zéro (c'est-à-dire que range(n) génère les nombres de 0 à n-1).
Notez bien que l'argument fourni n'est jamais dans la liste générée.
On peut aussi utiliser range avec deux, ou même trois arguments séparés par des virgules, afin de générer des séquences de nombres plus spécifiques :
Si vous avez du mal à assimiler l'exemple ci-dessus, considérez que range attend toujours trois arguments, que l'on pourrait intituler FROM, TO et STEP. FROM est la première valeur à générer, TO est la dernière (ou plutôt la dernière + un), et STEP le « pas » à sauter pour passer d'une valeur à la suivante. S'ils ne sont pas fournis, les paramètres FROM et STEP prennent leurs valeurs par défaut, qui sont respectivement 0 et 1.

### Parcours d'une liste à l'aide de for, range et len

L'instruction for est l'instruction idéale pour parcourir une liste :
Il est très pratique de combiner les fonctions range et len pour obtenir automatiquement tous les indices d'une séquence (liste ou chaîne). Exemple :
Mais il existe également une syntaxe adaptée à cela :
L'exécution de ce script donne le résultat :
Tableau à trois lignes :
Tableau à deux dimensions :

#### Une conséquence du typage dynamique

Le type de la variable utilisée avec l'instruction "for" est redéfini continuellement au fur et à mesure du parcours : même si les éléments d'une liste sont de types différents, on peut parcourir cette liste à l'aide de "for" sans qu'il ne s'ensuive une erreur, car le type de la variable de parcours s'adapte automatiquement à celui de l'élément en cours de lecture. Exemple :

### random

La plupart des programmes d'ordinateur font exactement la même chose chaque fois qu'on les exécute. De tels programmes sont dits déterministes. Le déterminisme est certainement une bonne chose : nous voulons évidemment qu'une même série de calculs appliquée aux mêmes données initiales aboutisse toujours au même résultat. Pour certaines applications, cependant, nous pouvons souhaiter que l'ordinateur soit imprévisible. Le cas des jeux constitue un exemple évident, mais il en existe bien d'autres.
Contrairement aux apparences, il n'est pas facile du tout d'écrire un algorithme qui soit réellement non-déterministe (c'est-à-dire qui produise un résultat totalement imprévisible). Il existe cependant des techniques mathématiques permettant de simuler plus ou moins bien l'effet du hasard. Des livres entiers ont été écrits sur les moyens de produire ainsi un hasard « de bonne qualité ». Nous n'allons évidemment pas développer ici une telle question, mais rien ne vous empêche de consulter à ce sujet votre professeur de mathématiques.
Dans son module random, Python propose toute une série de fonctions permettant de générer des nombres aléatoires qui suivent différentes distributions mathématiques. Nous n'examinerons ici que quelques-unes d'entre elles. Veuillez consulter la documentation en ligne pour découvrir les autres. Vous pouvez importer toutes les fonctions du module par :
Pour créer une liste de nombres réels aléatoires, de valeur comprise entre zéro et un :
Vous pouvez constater que nous avons pris le parti de construire d'abord une liste de zéros de taille n, et ensuite de remplacer les zéros par des nombres aléatoires.
Exercices
* Réécrivez la fonction list_aleat ci-dessus, en utilisant la méthode append pour construire la liste petit à petit à partir d'une liste vide (au lieu de remplacer les zéros d'une liste préexistante comme nous l'avons fait).
* Écrivez une fonction imprime_liste qui permette d'afficher ligne par ligne tous les éléments contenus dans une liste de taille quelconque. Le nom de la liste sera fourni en argument. Utilisez cette fonction pour imprimer la liste de nombres aléatoires générés par la fonction list_aleat. Ainsi par exemple, l'instruction imprime_liste(liste_aleat(8)) devra afficher une colonne de 8 nombres réels aléatoires.
Solution
* Réfléchissez !
* Réfléchissez !
Les nombres ainsi générés sont-ils vraiment aléatoires ? C'est difficile à dire. Si nous ne tirons qu'un petit nombre de valeurs, nous ne pouvons rien vérifier. Par contre, si nous utilisons un grand nombre de fois la fonction random, nous nous attendons à ce que la moitié des valeurs produites soient plus grandes que 0,5 (et l'autre moitié plus petites).
Affinons ce raisonnement. Les valeurs tirées sont toujours dans l'intervalle 0-1. Partageons cet intervalle en 4 fractions égales : de 0 à 0,25 , de 0,25 à 0,5 , de 0,5 à 0,75 , et de 0,75 à 1. Si nous tirons un grand nombre de valeurs au hasard, nous nous attendons à ce qu'il y en ait autant qui se situent dans chacune de nos 4 fractions. Et nous pouvons généraliser ce raisonnement à un nombre quelconque de fractions, du moment qu'elles soient égales.
Exercices
* Vous allez écrire un programme destiné à vérifier le fonctionnement du générateur de nombres aléatoires de Python en appliquant la théorie exposée ci-dessus. Votre programme devra donc : a) Demander à l'utilisateur le nombre de valeurs à tirer au hasard à l'aide de la fonction random. Il serait intéressant que le programme propose un nombre par défaut (1000 par exemple). b) Demander à l'utilisateur en combien de fractions il souhaite partager l'intervalle des valeurs possibles (c'est-à-dire l'intervalle de 0 à 1). Ici aussi, il faudrait proposer un nombre de par défaut (5 fractions, par exemple). Vous pouvez également limiter le choix de l'utilisateur à un nombre compris entre 2 et le 1/10e du nombre de valeurs tirées au hasard. c) Construire une liste de N compteurs (N étant le nombre de fractions souhaitées). Chacun d'eux sera évidemment initialisé à zéro. d) Tirer au hasard toutes les valeurs demandées, à l'aide de la fonction random, et mémoriser ces valeurs dans une liste. e) Mettre en œuvre un parcours de la liste des valeurs tirées au hasard (boucle), et effectuer un test sur chacune d'elles pour déterminer dans quelle fraction de l'intervalle 0-1 elle se situe. Incrémenter de une unité le compteur correspondant. f) Lorsque c'est terminé, afficher l'état de chacun des compteurs.
Solution
* # Test du générateur de nombres aléatoires : from random import random # tire au hasard un réel entre 0 et 1 n = raw_input("Nombre de valeurs à tirer au hasard (défaut = 1000) : ") if n == "": nVal =1000 else: nVal = int(n) n = raw_input("Nombre de fractions dans l'intervalle 0-1 (entre 2 et " + str(nVal/10) + ", défaut =5) : ") if n == "": nFra =5 else: nFra = int(n) if nFra < 2: nFra =2 elif nFra > nVal/10: nFra = nVal/10 print "Tirage au sort des", nVal, "valeurs ..." listVal = [0]*nVal # créer une liste de zéros for i in range(nVal): # puis modifier chaque élément listVal[i] = random print "Comptage des valeurs dans chacune des", nFra, "fractions ..." listCompt = [0]*nFra # créer une liste de compteurs # parcourir la liste des valeurs : for valeur in listVal: # trouver l'index de la fraction qui contient la valeur : index = int(valeur*nFra) # incrémenter le compteur correspondant : listCompt[index] = listCompt[index] +1 # afficher l'état des compteurs : for compt in listCompt: print compt,

#### Exemple de résultats affichés par un programme de ce type

Une bonne approche de ce genre de problème consiste à essayer d'imaginer quelles fonctions simples vous pourriez écrire pour résoudre l'une ou l'autre partie du problème, puis de les utiliser dans un ensemble plus vaste.
Par exemple, vous pourriez chercher à définir d'abord une fonction numeroFraction qui servirait à déterminer dans quelle fraction de l'intervalle 0-1 une valeur tirée se situe. Cette fonction attendrait deux arguments (la valeur tirée, le nombre de fractions choisi par l'utilisateur) et fournirait en retour l'index du compteur à incrémenter (c'est-à-dire le n° de la fraction correspondante). Il existe peut-être un raisonnement mathématique simple qui permette de déterminer l'index de la fraction à partir de ces deux arguments. Pensez notamment à la fonction intégrée int, qui permet de convertir un nombre réel en nombre entier en éliminant sa partie décimale.
Si vous ne trouvez pas, une autre réflexion intéressante serait peut-être de construire d'abord une liste contenant les valeurs « pivots » qui délimitent les fractions retenues (par exemple 0 – 0,25 – 0,5 – 0,75 - 1 dans le cas de 4 fractions). La connaissance de ces valeurs faciliterait peut-être l'écriture de la fonction numeroFraction que nous souhaitons mettre au point.
Si vous disposez d'un temps suffisant, vous pouvez aussi réaliser une version graphique de ce programme, qui présentera les résultats sous la forme d'un histogramme (diagramme « en bâtons »).

#### Tirage au hasard de nombres entiers

Lorsque vous développerez des projets personnels, il vous arrivera fréquemment de souhaiter pouvoir disposer d'une fonction qui permette de tirer au hasard un nombre entier entre certaines limites. Par exemple, si vous voulez écrire un programme de jeu dans lequel des cartes à jouer sont tirées au hasard (à partir d'un jeu ordinaire de 52 cartes), vous aurez certainement l'utilité d'une fonction capable de tirer au hasard un nombre entier compris entre 1 et 52.
Vous pouvez pour ce faire utiliser la fonction randrange du module random.
Cette fonction peut être utilisée avec 1, 2 ou 3 arguments.
Avec un seul argument, elle renvoie un entier compris entre zéro et la valeur de l'argument diminué d'une unité. Par exemple, randrange(6) renvoie un nombre compris entre 0 et 5.
Avec deux arguments, le nombre renvoyé est compris entre la valeur du premier argument et la valeur du second argument diminué d'une unité. Par exemple, randrange(2, 8) renvoie un nombre compris entre 2 et 7.
Si l'on ajoute un troisième argument, celui-ci indique que le nombre tiré au hasard doit faire partie d'une série limitée d'entiers, séparés les uns des autres par un certain intervalle, défini lui-même par ce troisième argument. Par exemple, randrange(3, 13, 3) renverra un des nombres de la série 3, 6, 9, 12 :
Exercices
* Écrivez un script qui tire au hasard des cartes à jouer. Le nom de la carte tirée doit être correctement présenté, « en clair ». Le programme affichera par exemple : Frappez <Enter> pour tirer une carte : Dix de Trèfle Frappez <Enter> pour tirer une carte : As de Carreau Frappez <Enter> pour tirer une carte : Huit de Pique Frappez <Enter> pour tirer une carte : etc ...
Solution
* # Tirage de cartes from random import randrange couleurs = ['Pique', 'Trèfle', 'Carreau', 'Cœur'] valeurs = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'valet', 'dame', 'roi', 'as'] # Construction de la liste des 52 cartes : carte = for coul in couleurs: for val in valeurs: carte.append("%s de %s" % (str(val), coul)) # Tirage au hasard : while 1: k = raw_input("Frappez <c> pour tirer une carte, <Enter> pour terminer ") if k =="": break r = randrange(52) print carte[r]

### map

Permet d'appliquer une fonction à toutes les entrées d'une liste. Par exemple pour les trimer :

## Exercices

Exercices
* Soient les listes suivantes : t1 = [31,28,31,30,31,30,31,31,30,31,30,31] t2 = ['Janvier','Février','Mars','Avril','Mai','Juin', 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'] Écrivez un petit programme qui insère dans la seconde liste tous les éléments de la première, de telle sorte que chaque nom de mois soit suivi du nombre de jours correspondant : ['Janvier',31,'Février',28,'Mars',31, etc.].
* Créez une liste A contenant quelques éléments. Effectuez une vraie copie de cette liste dans une nouvelle variable B. Suggestion : créez d'abord une liste B de même taille que A mais ne contenant que des zéros. Remplacez ensuite tous ces zéros par les éléments tirés de A.
* Même question, mais autre suggestion : créez d'abord une liste B vide. Remplissez-la ensuite à l'aide des éléments de A ajoutés l'un après l'autre.
* Même question, autre suggestion encore : pour créer la liste B, découpez dans la liste A une tranche incluant tous les éléments (à l'aide de l'opérateur [:]).
* Un nombre premier est un nombre qui n'est divisible que par un et par lui-même. Écrivez un programme qui établisse la liste de tous les nombres premiers compris entre 1 et 1000, en utilisant la méthode du crible d'Ératosthène : Lorsque vous aurez parcouru ainsi toute la liste, les indices des éléments qui seront restés à 1 seront les nombres premiers recherchés. En effet, à partir de l'indice 2, vous annulez tous les éléments d'indices pairs : 4, 6, 8, 10, etc. Avec l'indice 3, vous annulez les éléments d'indices 6, 9, 12, 15, etc., et ainsi de suite. Seuls resteront à 1 les éléments dont les indices sont effectivement des nombres premiers.
** Créez une liste de 1000 éléments, chacun initialisé à la valeur 1.
** Parcourez cette liste à partir de l'élément d'indice 2 : si l'élément analysé possède la valeur 1, mettez à zéro tous les autres éléments de la liste, dont les indices sont des multiples entiers de l'indice auquel vous êtes arrivé.
Solution
* # Insertion de nouveaux éléments dans une liste existante t1 = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] t2 = ['Janvier','Février','Mars','Avril','Mai','Juin', 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'] c, d = 1, 0 while d < 12 : t2[c:c] = [t1[d]] # ! l'élément inséré doit être une liste c, d = c+2, d+1 </pre> </li> <li>Réfléchissez !</li> <li>Réfléchissez !</li> <li>Réfléchissez !</li> <li> <syntaxhighlight lang=python> # Crible d’Ératosthène pour rechercher les nombres premiers de 1 à 999 # Créer une liste de 1000 éléments 1 (leurs indices vont de 0 à 999) : lst = [1]*1000 # Parcourir la liste à partir de l'élément d'indice 2: for i in range(2,1000): # Mettre à zéro les éléments suivants dans la liste, # dont les indices sont des multiples de i : for j in range(i*2, 1000, i): lst[j] = 0 # Afficher les indices des éléments restés à 1 (on ignore l'élément 0) : for i in range(1,1000): if lst[i]: print i, </syntaxhighlight> </li> </ol> </div> <div style="border-left:2px solid grey; padding-left:1em" class="exercice"> <strong>Exercices</strong> <ol> <li>Déterminez vous-même ce qui se passe lorsque l'un ou l'autre des indices de découpage est erroné, et décrivez cela le mieux possible (si le second indice est plus petit que le premier, par exemple, ou bien si le second indice est plus grand que la taille de la chaîne).</li> <li>Découpez une grande chaîne en fragments de cinq caractères chacun. Rassemblez ces morceaux dans l'ordre inverse.</li> <li>Tâchez d'écrire un script qui fera exactement le contraire de ce que fait l'opérateur d'indexage () : au lieu de partir d'un index donné pour retrouver le caractère correspondant, il devra retrouver l'index correspondant à un caractère donné, à partir du nom de la chaîne à traiter et du caractère à trouver. Exemple : pour <code>"Juliette & Roméo", "&"</code> il devra afficher : 9, ou -1 si le caractère est introuvable. <li>Améliorez le script en lui ajoutant une troisième variable : l'index à partir duquel la recherche doit s'effectuer dans la chaîne. Ainsi par exemple, pour : <code>"César & Cléopâtre", "r", 5</code>, il devra afficher : 15 (et non 4 !)</li> <li>Écrivez un script qui compte le nombre d'occurrences d'un caractère donné dans une chaîne. Ainsi, pour <code>"ananas au jus", "a"</code> il devra afficher : 4. </li> </ol> ---- <strong>Solution</strong> <ol> <li>''IndexError: list index out of range''</li> <li> <syntaxhighlight lang=python> # Découpage d'une chaîne en fragments : chain ="abcdefghijklmnopqrstuvwxyz123456789" n = 5 # Découpage de "chain" en une liste de fragments de n caractères" d, f = 0, n # indices de début et de fin de fragment tt = # liste à construire while d < len(chain): if f > len(chain): # on ne peut pas découper au-delà de la fin f = len(chain) fr = chain[d:f] # découpage d'un fragment tt.append(fr) # ajout du fragment à la liste d, f = f, f + n # indices suivants print(tt) # Rassemble les éléments de la liste tt dans l'ordre inverse" chain = "" # chaîne à construire i = len(tt) # on commence par la fin de la liste while i > 0 : i = i - 1 # le dernier élément possède l'indice n - 1 chain = chain + tt[i] print(chain) </syntaxhighlight> </li> <li> <syntaxhighlight lang=python> # Rechercher l'indice d'un caractère dans une chaîne chain, car = "Coucou c'est moi", "z" start = 0 # Trouve l'indice du caractère car dans "chain" i = start while i < len(chain): if chain[i] == car: print(i) # le caractère est trouvé -> on termine i = i + 1 print(-1) # toute la chaîne a été scannée sans succès # Autres tests : chain, car = "Juliette & Roméo", "&" chain, car, start = "César & Cléopâtre", "r", 5 </syntaxhighlight> </li> <li>Réfléchissez !</li> <li>Réfléchissez !</li> </ol> </div> <div style="border-left:2px solid grey; padding-left:1em" class="exercice"> <strong>Exercices</strong> <ol> <li>Soient les listes suivantes : <syntaxhighlight lang=python> t1 = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] t2 = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'] </syntaxhighlight> Écrivez un petit programme qui crée une nouvelle liste t3. Celle-ci devra contenir tous les éléments des deux listes en les alternant, de telle manière que chaque nom de mois soit suivi du nombre de jours correspondant : <code>['Janvier',31,'Février',28,'Mars',31, etc.]</code>.</li> <li>Écrivez un programme qui affiche « proprement » tous les éléments d'une liste. Si on l'appliquait par exemple à la liste t2 de l'exercice ci-dessus, on devrait obtenir : <pre> Janvier Février Mars Avril Mai Juin Juillet Août Septembre Octobre Novembre Décembre </pre></li> <li>Écrivez un programme qui recherche le plus grand élément présent dans une liste donnée. Par exemple, si on l'appliquait à la liste <code>[32, 5, 12, 8, 3, 75, 2, 15]</code>, ce programme devrait afficher : <pre> le plus grand élément de cette liste a la valeur 75. </pre></li> <li>Écrivez un programme qui analyse un par un tous les éléments d'une liste de nombres (par exemple celle de l'exercice précédent) pour générer deux nouvelles listes. L'une contiendra seulement les nombres pairs de la liste initiale, et l'autre les nombres impairs. Par exemple, si la liste initiale est celle de l'exercice précédent, le programme devra construire une liste pairs qui contiendra <code>[32, 12, 8, 2]</code>, et une liste impairs qui contiendra <code>[5, 3, 75, 15]</code>. Astuce : pensez à utiliser l'opérateur modulo (%) déjà cité précédemment.</li> <li>Écrivez un programme qui analyse un par un tous les éléments d'une liste de mots (par exemple : <code>['Jean', 'Maximilien', 'Brigitte', 'Sonia', 'Jean-Pierre', 'Sandra']</code> pour générer deux nouvelles listes. L'une contiendra les mots comportant moins de 6 caractères, l'autre les mots comportant 6 caractères ou davantage.</li> </ol> ---- <strong>Solution</strong> <ol> <li> <syntaxhighlight lang=python> # Combinaison de deux listes en une seule # Listes fournies au départ : t1 = [31,28,31,30,31,30,31,31,30,31,30,31] t2 = ['Janvier','Février','Mars','Avril','Mai','Juin', 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'] # Nouvelle liste à construire (vide au départ) : t3 = # Boucle de traitement : i = 0 while i < len(t1): t3.append(t2[i]) t3.append(t1[i]) i = i + 1 # Affichage : print t3 </syntaxhighlight> </li> <li> <syntaxhighlight lang=python> # Affichage des éléments d'une liste # Liste fournie au départ : t2 = ['Janvier','Février','Mars','Avril','Mai','Juin', 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'] # Affichage : i = 0 while i < len(t2): print t2[i], i = i + 1 </syntaxhighlight> </li> <li> <syntaxhighlight lang=python> # Recherche du plus grand élément d'une liste # Liste fournie au départ : tt = [32, 5, 12, 8, 3, 75, 2, 15] # Au fur et à mesure du traitement de la liste, on mémorisera dans # la variable ci-dessous la valeur du plus grand élément déjà trouvé : max = 0 # Examen de tous les éléments : i = 0 while i < len(tt): if tt[i] > max: max = tt[i] # mémorisation d'un nouveau maximum i = i + 1 # Affichage : print "Le plus grand élément de cette liste a la valeur", max </syntaxhighlight> </li> <li> <syntaxhighlight lang=python> # Séparation des nombres pairs et impairs # Liste fournie au départ : tt = [32, 5, 12, 8, 3, 75, 2, 15] pairs = impairs = # Examen de tous les éléments : i = 0 while i < len(tt): if tt[i] % 2 == 0: pairs.append(tt[i]) else: impairs.append(tt[i]) i = i + 1 # Affichage : print "Nombres pairs :", pairs print "Nombres impairs :", impairs </syntaxhighlight> </li> <li>Réfléchissez !</li> </ol> </div> <div style="border-left:2px solid grey; padding-left:1em" class="exercice"> <strong>Exercices</strong> # Écrivez un script qui génère la liste des carrés et des cubes des nombres de 20 à 40. # Écrivez un script qui crée automatiquement la liste des sinus des angles de 0° à 90° , par pas de 5°. Attention : la fonction sin du module math considère que les angles sont fournis en radians (360° = 2 p radians) # Écrivez un script qui permette d'obtenir à l'écran les 15 premiers termes des tables de multiplication par 2, 3, 5, 7, 11, 13, 17, 19 (ces nombres seront placés au départ dans une liste) sous la forme d'une table semblable à la suivante :<br /><code>2 4 6 8 10 12 14 16 18 20 22 24 26 28 30</code><br /><code>3 6 9 12 15 18 21 24 27 30 33 36 39 42 45</code><br /><code>5 10 15 20 25 30 35 40 45 50 55 60 65 70 75</code><br />etc. # Soit la liste suivante :<br /><code>['Jean-Michel', 'Marc', 'Vanessa', 'Anne', 'Maximilien', 'Alexandre-Benoît', 'Louise']</code><br />Écrivez un script qui affiche chacun de ces noms avec le nombre de caractères correspondant. # Vous disposez d'une liste de nombres entiers quelconques, certains d'entre eux étant présents en plusieurs exemplaires. Écrivez un script qui recopie cette liste dans une autre, en omettant les doublons. La liste finale devra être triée. # Écrivez un script qui recherche le mot le plus long dans une phrase donnée (l'utilisateur du programme doit pouvoir entrer une phrase de son choix). # Écrivez un script capable d'afficher la liste de tous les jours d'une année imaginaire, laquelle commencerait un Jeudi. Votre script utilisera lui-même trois listes : une liste des noms de jours de la semaine, une liste des noms des mois, et une liste des nombres de jours que comportent chacun des mois (ne pas tenir compte des années bissextiles).<br />Exemple de sortie :<br /><code>Jeudi 1 Janvier Vendredi 2 Janvier Samedi 3 Janvier Dimanche 4 Janvier</code><br />... et ainsi de suite jusqu'au <code>Jeudi 31 Décembre</code>. # Vous avez à votre disposition un fichier texte qui contient un certain nombre de noms d'élèves. Écrivez un script qui effectue une copie triée de ce fichier. # Écrivez un script permettant de trier une liste. Il ne pourra pas utiliser la méthode intégrée "sort" de Python : vous devez donc définir vous-même l'algorithme de tri. ---- <strong>Solution</strong> <ol> <li>Réfléchissez !</li> <li>Réfléchissez !</li> <li> <syntaxhighlight lang=python> # Affichage de tables de multiplication m, n = 3, 15 chain ="" for i in range(n): v = m * (i+1) # calcul d'un des termes chain = chain + "%4d" % (v) # formatage à 4 caractères print(chain) </syntaxhighlight> 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 </li> <li> <syntaxhighlight lang=python> # Simple parcours d'une liste : lst = ['Jean-Michel', 'Marc', 'Vanessa', 'Anne', 'Maximilien', 'Alexandre-Benoît', 'Louise'] for e in lst: print("%s : %s caractères" % (e, len(e))) </syntaxhighlight> </li> <li> <syntaxhighlight lang=python> # Élimination de doublons lst = [9, 12, 40, 5, 12, 3, 27, 5, 9, 3, 8, 22, 40, 3, 2, 4, 6, 25] lst2 = for el in lst: if el not in lst2: lst2.append(el) lst2.sort print(lst2) </syntaxhighlight> </li> <li>Réfléchissez !</li> <li> <syntaxhighlight lang=python> # Afficher tous les jours d'une année : ## Cette variante utilise une liste de listes ## ## (que l'on pourrait aisément remplacer par deux listes distinctes) # La liste ci-dessous contient deux éléments qui sont eux-mêmes des listes. # l'élément 0 contient les nombres de jours de chaque mois, tandis que # l'élément 1 contient les noms des douze mois : mois = [[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']] jour = ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'] ja, jm, js, m = 0, 0, 0, 0 while ja <365: ja, jm = ja +1, jm +1 # ja = jour dans l'année, jm = jour dans le mois js = (ja +3) % 7 # js = jour de la semaine. Le décalage ajouté # permet de choisir le jour de départ if jm > mois[0][m]: # élément m de l'élément 0 de la liste jm, m = 1, m+1 print jour[js], jm, mois[1][m] # élément m de l'élément 1 de la liste </syntaxhighlight> </li> <li>Réfléchissez !</li> <li>Réfléchissez !</li> </ol> </div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> =Tuples= == Description d'un tuple == Vous devez vous rappeler une autre différence importante entre chaînes et listes : il n'est pas possible de changer les caractères au sein d'une chaîne existante, alors que vous pouvez modifier les éléments d'une liste. En d'autres termes, les listes sont des séquences modifiables, alors que les chaînes sont des séquences non-modifiables. Exemple : <pre> >>> liste =['jambon','fromage','miel','confiture','chocolat'] >>> liste[1:3] =['salade'] >>> print liste ['jambon', 'salade', 'confiture', 'chocolat'] >>> chaine ='Roméo préfère Juliette' >>> chaine[14:] ='Brigitte' ***** ==> Erreur: object doesn't support slice assignment ***** </pre> Nous essayons de modifier la fin de la chaîne, mais cela ne marche pas. La seule possibilité d'arriver à nos fins est de créer une nouvelle chaîne et d'y recopier ce que nous voulons changer : <pre> >>> chaine = chaine[:14] +'Brigitte' >>> print chaine Roméo préfère Brigitte </pre> Python propose un type de données appelé ''[[wikt:tuple|tuple]]'' (anglicisme informatique signifiant "Table [[wikt:uplet|UPLEt]]"), qui est assez semblable à une liste mais qui n'est pas modifiable. Les tuples sont donc préférables aux listes partout où l'on veut être certain que les données transmises ne soient pas modifiées par erreur au sein d'un programme. En outre, les tuples sont moins « gourmands » en ressources système (ils occupent moins de place en mémoire). Du point de vue de la syntaxe, un tuple est une collection d'éléments séparés par des virgules : <pre> >>> tuple = 'a', 'b', 'c', 'd', 'e' >>> print(tuple) ('a', 'b', 'c', 'd', 'e') </pre> Pour améliorer la lisibilité du code, il est vivement conseillé de déclarer le tuple en évidence en l'enfermant dans une paire de parenthèses, comme l'instruction "<code>print</code>" de Python le fait elle-même. <pre> >>> tuple = ('a', 'b', 'c', 'd', 'e') </pre> Les opérations que l'on peut effectuer sur des tuples sont syntaxiquement similaires à celles que l'on effectue sur les listes, si ce n'est que les tuples ne sont pas modifiables : <pre> >>> print(tuple[2:4]) ('c', 'd') >>> tuple[1:3] = ('x', 'y') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> tuple = ('André',) + tuple[1:] >>> print(tuple) ('André', 'b', 'c', 'd', 'e') </pre> Remarquez qu'il faut toujours au moins une virgule pour définir un tuple (le dernier exemple ci-dessus utilise un tuple contenant un seul élément : <code>'André'</code>). <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> =Dictionnaires= == Déclarations == Le dictionnaire ou [[w:fr:tableau associatif|tableau associatif]] n'est pas une séquence mais un autre type composite. Ils ressemblent aux listes dans une certaine mesure (ils sont modifiables comme elles), mais les éléments que nous allons y enregistrer ne seront pas disposés dans un ordre immuable. En revanche, nous pourrons accéder à n'importe lequel d'entre eux à l'aide d'un index spécifique que l'on appellera une clé, laquelle pourra être alphabétique, numérique, ou même d'un type composite sous certaines conditions. <div class="remarque">&nbsp;Comme dans une liste, les éléments mémorisés dans un dictionnaire peuvent être de n'importe quel type (valeurs numériques, chaînes, listes, etc.).</div> == Création d'un dictionnaire == À titre d'exemple, nous allons créer un dictionnaire de langue, pour la traduction de termes informatiques anglais en français. Dans ce dictionnaire, les index seront des chaînes de caractères. Puisque le type dictionnaire est un type modifiable, nous pouvons commencer par créer un dictionnaire vide, puis le remplir petit à petit. Du point de vue syntaxique, on reconnaît une structure de données de type dictionnaire au fait que ses éléments sont enfermés dans ''une paire d'accolades''. Un dictionnaire vide sera donc noté <code>{ }</code> : <syntaxhighlight lang=python> dico = dico['computer'] = 'ordinateur' dico['mouse'] ='souris' dico['keyboard'] ='clavier' print dico {'computer': 'ordinateur', 'keyboard': 'clavier', 'mouse': 'souris'} </syntaxhighlight> Comme vous pouvez l'observer dans la ligne ci-dessus, un dictionnaire apparaît comme une série d'éléments séparés par des virgules (le tout étant enfermé entre deux accolades}. Chacun de ces éléments est constitué d'une paire d'objets : un index et une valeur, séparés par un double point. Dans un dictionnaire, les index s'appellent des ''clés'', et les éléments peuvent donc s'appeler ''des paires clé-valeur''. Vous pouvez constater que l'ordre dans lequel les éléments apparaissent à la dernière ligne ne correspond pas à celui dans lequel nous les avons fournis. Cela n'a strictement aucune importance : nous n'essaierons jamais d'extraire une valeur d'un dictionnaire à l'aide d'un index numérique. Au lieu de cela, nous utiliserons les clés : <pre> >>> print dico['mouse'] souris </pre> Contrairement à ce qui se passe avec les listes, il n'est pas nécessaire de faire appel à une méthode particulière pour ajouter de nouveaux éléments à un dictionnaire : il suffit de créer une nouvelle paire clé-valeur. == Opérations sur les dictionnaires == Pour en enlever, vous utiliserez l'instruction <code>del</code>. Créons pour l'exemple un autre dictionnaire, destiné cette fois à contenir l'inventaire d'un stock de fruits. Les index (ou clés) seront les noms des fruits, et les valeurs seront les masses de ces fruits répertoriées dans le stock (il s'agit donc cette fois de valeurs de type numérique). <pre> >>> invent = {'pommes': 430, 'bananes': 312, 'oranges' : 274, 'poires' : 137} >>> print invent {'oranges': 274, 'pommes': 430, 'bananes': 312, 'poires': 137} </pre> Si le patron décide de liquider toutes les pommes et de ne plus en vendre, nous pouvons enlever cette entrée dans le dictionnaire : <pre> >>> del invent['pommes'] >>> print invent {'oranges': 274, 'bananes': 312, 'poires': 137} </pre> La fonction <code>len</code> est utilisable avec un dictionnaire : elle en renvoie le nombre d'éléments. == Les dictionnaires sont des objets == On peut appliquer aux dictionnaires un certain nombre de ''méthodes'' spécifiques : === ''keys'' et ''values'' === La méthode <code>keys</code> renvoie la liste des clés utilisées dans le dictionnaire : <pre> >>> print dico.keys ['computer', 'keyboard', 'mouse'] </pre> La méthode <code>values</code> renvoie la liste des valeurs mémorisées dans le dictionnaire : <pre> >>> print invent.values [274, 312, 137] </pre> === ''has_key'' === La méthode <code>has_key</code> permet de savoir si un dictionnaire comprend une clé déterminée. On fournit la clé en argument, et la méthode renvoie une valeur 'vraie' ou 'fausse' (en fait, 1 ou 0), suivant que la clé est présente ou pas : <div style="display: flex;flex-wrap: wrap;color: #f16600;"> <div style="width: 40px; margin-right: 1em;"> [[Fichier:OOjs UI icon alert-warning.svg|40px|alt=Logo|link=]] </div> <div style="width: calc(100% - 90px); margin-left: 1em;"> Cette méthode ne fonctionne plus depuis Python 3.x, où il faut utiliser le nom de la clé <code>in</code> nom du dictionnaire. </div> </div> <pre> >>> print invent.has_key('bananes') 1 >>> print 'bananes' in invent 1 >>> if invent.has_key('pommes'): print 'nous avons des pommes' else: print 'pas de pommes, sorry' pas de pommes, sorry </pre> === ''items'' === La méthode <code>items</code> extrait du dictionnaire une liste équivalente de tuples : <pre> >>> print invent.items [('oranges', 274), ('bananes', 312), ('poires', 137)] </pre> Il est donc utilisé pour les "foreach" : <syntaxhighlight lang=python> for key, value in invent.items: print "Clé : %s, valeur : %s." % (key, value) </syntaxhighlight> === ''copy'' === La méthode <code>copy</code> permet d'effectuer une vraie copie d'un dictionnaire. Il faut savoir en effet que la simple affectation d'un dictionnaire existant à une nouvelle variable crée seulement une nouvelle référence vers le même objet, et non un nouvel objet (''aliasing''). Par exemple, l'instruction ci-dessous ne définit pas un nouveau dictionnaire (contrairement aux apparences) : <syntaxhighlight lang=python> >>> stock = invent >>> print stock {'oranges': 274, 'bananes': 312, 'poires': 137} >>> del invent['bananes'] >>> print stock {'oranges': 274, 'poires': 137} </syntaxhighlight> Si nous modifions "invent", alors <code>stock</code> aussi est modifié, et vice-versa (ces deux noms désignent en effet le même objet dictionnaire dans la mémoire de l'ordinateur). Pour obtenir une vraie copie (indépendante) d'un dictionnaire préexistant, il faut employer la méthode <code>copy</code> : <syntaxhighlight lang=python> >>> magasin = stock.copy >>> magasin['prunes'] = 561 >>> print magasin {'oranges': 274, 'prunes': 561, 'poires': 137} >>> print stock {'oranges': 274, 'poires': 137} >>> print invent {'oranges': 274, 'poires': 137} </syntaxhighlight> === ''update'' === Il est possible de concaténer deux dictionnaires avec cette méthode : <syntaxhighlight lang="python"> >>> d = {'apples': 1, 'oranges': 3, 'pears': 2} >>> ud = {'pears': 4, 'grapes': 5, 'lemons': 6} >>> d.update(ud) >>> d {'grapes': 5, 'pears': 4, 'lemons': 6, 'apples': 1, 'oranges': 3} >>> </syntaxhighlight> <div class="remarque">&nbsp;les doublons sont automatiquement fusionnés.</div> === ''sorted'' === Pour trier un dictionnaire par clé : <syntaxhighlight lang="python"> d = sorted(d.items, key=lambda x: x[0]) </syntaxhighlight> Pour trier par valeur : <syntaxhighlight lang="python"> d = sorted(d.items, key=lambda x: x[1]) </syntaxhighlight> Pour l'inverse, ajouter : <code>, reverse=True</code>. == Parcours d'un dictionnaire == Vous pouvez utiliser une boucle for pour traiter successivement tous les éléments contenus dans un dictionnaire, mais attention : * Au cours de l'itération, ce sont les clés utilisées dans le dictionnaire qui seront successivement affectées à la variable de travail, et non les valeurs. * L'ordre dans lequel les éléments seront extraits est imprévisible (puisqu'un dictionnaire n'est pas une séquence). Exemple : <pre> >>> invent ={"oranges":274, "poires":137, "bananes":312} >>> for clef in invent: ... print clef poires bananes oranges </pre> Si vous souhaitez effectuer un traitement sur les valeurs, il vous suffit alors de récupérer chacune d'elles à partir de la clé correspondante : <pre> for clef in invent: print clef, invent[clef] poires 137 bananes 312 oranges 274 </pre> Cette manière de procéder n'est cependant pas idéale, ni en termes de performances ni même du point de vue de la lisibilité. Il est recommandé de plutôt faire appel à la méthode <code>items</code> décrite à la section précédente : <pre> for clef, valeur in invent.items: print clef, valeur poires 137 bananes 312 oranges 274 </pre> == Les clés ne sont pas nécessairement des chaînes de caractères == Jusqu'à présent nous avons décrit des dictionnaires dont les clés étaient à chaque fois des valeurs de type ''string''. En fait nous pouvons utiliser en guise de clés n'importe quel type de donnée non modifiable : des entiers, des réels, des chaînes de caractères, et même des tuples. Considérons par exemple que nous voulions répertorier les arbres remarquables situés dans un grand terrain rectangulaire. Nous pouvons pour cela utiliser un dictionnaire, dont les clés seront des tuples indiquant les coordonnées x,y de chaque arbre : <pre> >>> arb = >>> arb[(1,2)] = 'Peuplier' >>> arb[(3,4)] = 'Platane' >>> arb[6,5] = 'Palmier' >>> arb[5,1] = 'Cycas' >>> arb[7,3] = 'Sapin' >>> print arb {(3, 4): 'Platane', (6, 5): 'Palmier', (5, 1): 'Cycas', (1, 2): 'Peuplier', (7, 3): 'Sapin'} >>> print arb[(6,5)] palmier </pre> [[Image:Apprendre à programmer avec Python 33.png|center|foret disposée en grille dont les arbres sont générés par un dictionnaire]] Vous pouvez remarquer que nous avons allégé l'écriture à partir de la troisième ligne, en profitant du fait que les parenthèses délimitant les tuples sont facultatives (à utiliser avec prudence !). Dans ce genre de construction, il faut garder à l'esprit que le dictionnaire contient des éléments seulement pour certains couples de coordonnées. Ailleurs, il n'y a rien. Par conséquent, si nous voulons interroger le dictionnaire pour savoir ce qui se trouve là où il n'y a rien, comme par exemple aux coordonnées (2,1), nous allons provoquer une erreur : <pre> >>> print arb[1,2] Peuplier >>> print arb[2,1] ***** Erreur : KeyError: (2, 1) ***** </pre> Pour résoudre ce petit problème, nous pouvons utiliser la méthode <code>get</code> : <pre> >>> print arb.get((1,2),'néant') Peuplier >>> print arb.get((2,1),'néant') néant </pre> Le premier argument transmis à cette méthode est la clé de recherche, le second argument est la valeur que nous voulons obtenir en retour si la clé n'existe pas dans le dictionnaire. == Les dictionnaires ne sont pas des séquences == Comme vous l'avez vu plus haut, les éléments d'un dictionnaire ne sont pas disposés dans un ordre particulier. Des opérations comme la concaténation et l'extraction (d'un groupe d'éléments contigus) ne peuvent donc tout simplement pas s'appliquer ici. Si vous essayez tout de même, Python lèvera une erreur lors de l'exécution du code : <syntaxhighlight lang=python> >>> print arb[1:3] ***** Erreur : KeyError: slice(1, 3, None) ***** </syntaxhighlight> Vous avez vu également qu'il suffit d'affecter un nouvel indice (une nouvelle clé) pour ajouter une entrée au dictionnaire. Cela ne marcherait pas avec les listes : <syntaxhighlight lang=python> >>> invent['cerises'] = 987 >>> print invent {'oranges': 274, 'cerises': 987, 'poires': 137} >>> liste =['jambon', 'salade', 'confiture', 'chocolat'] >>> liste[4] ='salami' ***** IndexError: list assignment index out of range ***** </syntaxhighlight> Du fait qu'ils ne sont pas des séquences, les dictionnaires se révèlent donc particulièrement précieux pour gérer des ensembles de données où l'on est amené à effectuer fréquemment des ajouts ou des suppressions, dans n'importe quel ordre. Ils remplacent avantageusement les listes lorsqu'il s'agit de traiter des ensembles de données numérotées, dont les numéros ne se suivent pas. Exemple : <pre> >>> client = >>> client[4317] = "Dupond" >>> client[256] = "Durand" >>> client[782] = "Schmidt" </pre> etc. <div style="border-left:2px solid grey; padding-left:1em" class="exercice"> <strong>Exercices</strong> <ol> <li>Écrivez un script qui crée un mini-système de base de données fonctionnant à l'aide d'un dictionnaire, et dans lequel vous mémoriserez les noms d'une série de copains, leur âge et leur taille. Votre script devra comporter deux fonctions : la première pour le remplissage du dictionnaire, et la seconde pour sa consultation. Dans la fonction de remplissage, utilisez une boucle pour accepter les données entrées par l'utilisateur. Dans le dictionnaire, le nom de l'élève servira de clé d'accès, et les valeurs seront constituées de tuples (âge, taille), dans lesquels l'âge sera exprimé en années (donnée de type entier), et la taille en mètres (donnée de type réel). La fonction de consultation comportera elle aussi une boucle, dans laquelle l'utilisateur pourra fournir un nom quelconque pour obtenir en retour le couple « âge, taille » correspondant. Le résultat de la requête devra être une ligne de texte bien formatée, telle par exemple : « Nom : Jean Dhoute - âge : 15 ans - taille : 1.74 m ».</li> <li>Écrivez une fonction qui échange les clés et les valeurs d'un dictionnaire (ce qui permettra par exemple de transformer un dictionnaire anglais/français en un dictionnaire français/anglais). (On suppose que le dictionnaire ne contient pas plusieurs valeurs identiques).</li> </ol> ---- <strong>Solution</strong> <ol> <li> <syntaxhighlight lang=python> #!/usr/bin/env python # coding: utf-8 # Création du dictionnaire dico = while 1: choix = raw_input("Choisissez : (R)emplir - (C)onsulter - (T)erminer : ") if choix.upper == 'T': break elif choix.upper == 'R': nom = raw_input("Entrez le nom (ou <enter> pour terminer) : ") if nom == "": break age = int(raw_input("Entrez l'âge (nombre entier !) : ")) taille = float(raw_input("Entrez la taille (en mètres) : ")) dico[nom] = (age, taille) elif choix.upper == 'C': # Consultation nom = raw_input("Entrez le nom (ou <enter> pour terminer) : ") if nom == "": break if dico.has_key(nom): # le nom est-il répertorié ? item = dico[nom] # consultation proprement dite age, taille = item[0], item[1] print "Nom : %s - âge : %s ans - taille : %s m."\ % (nom, age, taille) else: print "*** nom inconnu ! ***" </syntaxhighlight> </li> <li> <syntaxhighlight lang=python> # Échange des clés et des valeurs dans un dictionnaire dico = {'Computer':'Ordinateur', 'Mouse':'Souris', 'Keyboard':'Clavier', 'Hard disk':'Disque dur', 'Screen':'Ecran'} print(dico) dic_inv = for cle in dico: item = dico[cle] dic_inv[item] = cle print(dic_inv) </syntaxhighlight> </li> </ol> </div> == Construction d'un histogramme à l'aide d'un dictionnaire == Les dictionnaires constituent un outil très élégant pour construire des histogrammes. Supposons par exemple que nous voulions établir l'histogramme qui représente la fréquence d'utilisation de chacune des lettres de l'alphabet dans un texte donné. L'algorithme permettant de réaliser ce travail est extraordinairement simple si on le construit sur base d'un dictionnaire : <pre> >>> texte ="les saucisses et saucissons secs sont dans le saloir" >>> lettres = >>> for c in texte: lettres[c] = lettres.get(c, 0) + 1 >>> print lettres {'t': 2, 'u': 2, 'r': 1, 's': 14, 'n': 3, 'o': 3, 'l': 3, 'i': 3, 'd': 1, 'e': 5, 'c': 3, ' ': 8, 'a': 4} </pre> Nous commençons par créer un dictionnaire vide : <code>lettres</code>. Ensuite, nous allons remplir ce dictionnaire en utilisant les caractères de l'alphabet en guise de clés. Les valeurs que nous mémoriserons pour chacune de ces clés seront les fréquences des caractères correspondants dans le texte. Afin de calculer celles-ci, nous effectuons un parcours de la chaîne de caractères texte. Pour chacun de ces caractères, nous interrogeons le dictionnaire à l'aide de la méthode <code>get</code>, en utilisant le caractère en guise de clé, afin d'y lire la fréquence déjà mémorisée pour ce caractère. Si cette valeur n'existe pas encore, la méthode <code>get</code> doit renvoyer une valeur nulle. Dans tous les cas, nous incrémentons la valeur trouvée, et nous la mémorisons dans le dictionnaire à l'emplacement qui correspond à la clé (c'est-à-dire au caractère en cours de traitement). Pour fignoler notre travail, nous pouvons encore souhaiter afficher l'histogramme dans l'ordre alphabétique. Pour ce faire, nous pensons immédiatement à la méthode <code>sort</code>, mais celle-ci ne peut s'appliquer qu'aux listes. Qu'à cela ne tienne ! Nous avons vu plus haut comment nous pouvions convertir un dictionnaire en une liste de tuples : <pre> >>> lettres_triees = lettres.items >>> lettres_triees.sort >>> print lettres_triees [(' ', 8), ('a', 4), ('c', 3), ('d', 1), ('e', 5), ('i', 3), ('l', 3), ('n', 3), ('o', 3), ('r', 1), ('s', 14), ('t', 2), ('u', 2)] </pre> <div style="border-left:2px solid grey; padding-left:1em" class="exercice"> <strong>Exercices</strong> # Vous avez à votre disposition un fichier texte quelconque (pas trop gros). Écrivez un script qui compte les occurrences de chacune des lettres de l'alphabet dans ce texte (on ne tiendra pas compte du problème des lettres accentuées).. # Modifiez le script ci-dessus afin qu'il établisse une table des occurrences de chaque mot dans le texte. Conseil : dans un texte quelconque, les mots ne sont pas seulement séparés par des espaces, mais également par divers signes de ponctuation. Pour simplifier le problème, vous pouvez commencer par remplacer tous les caractères non-alphabétiques par des espaces, et convertir la chaîne résultante en une liste de mots à l'aide de la méthode <code>split</code>. # Vous avez à votre disposition un fichier texte quelconque (pas trop gros). Écrivez un script qui analyse ce texte, et mémorise dans un dictionnaire l'emplacement exact de chacun des mots (compté en nombre de caractères à partir du début). Lorsqu'un même mot apparaît plusieurs fois, tous ses emplacements doivent être mémorisés : chaque valeur de votre dictionnaire doit donc être une liste d'emplacements. ---- <strong>Solution</strong> <ol> <li> <syntaxhighlight lang=python> # histogramme nFich = raw_input('Nom du fichier : ') fi = open(nFich, 'r') texte = fi.read # conversion du fichier en une chaîne de caractères fi.close print texte dico = for c in texte: c = c.upper # conversion de toutes les lettres en majuscules dico[c] = dico.get(c, 0) +1 liste = dico.items liste.sort print liste </syntaxhighlight> </li> <li> <syntaxhighlight lang=python> nFich = raw_input('Nom du fichier à traiter : ') fi = open(nFich, 'r') texte = fi.read fi.close # afin de pouvoir aisément séparer les mots du texte, on commence # par convertir tous les caractères non-alphabétiques en espaces : alpha = "abcdefghijklmnopqrstuvwxyzéèàùçâêîôûäëïöü" lettres = '' # nouvelle chaîne à construire for c in texte: c = c.lower # conversion de chaque caractère en minuscule if c in alpha: lettres = lettres + c else: lettres = lettres + ' ' # conversion de la chaîne résultante en une liste de mots : mots = lettres.split # construction de l'histogramme : dico = for m in mots: dico[m] = dico.get(m, 0) +1 liste = dico.items # tri de la liste résultante : liste.sort # affichage en clair : for item in liste: print item[0], ":", item[1] </syntaxhighlight> </li> <li> <syntaxhighlight lang=python> # encodage d'un texte dans un dictionnaire nFich = raw_input('Nom du fichier à traiter : ') fi = open(nFich, 'r') texte = fi.read fi.close # On considère que les mots sont des suites de caractères faisant partie # de la chaîne ci-dessous. Tous les autres sont des séparateurs : alpha = "abcdefghijklmnopqrstuvwxyzéèàùçâêîôûäëïöü" # construction du dictionnaire : dico = # parcours de tous les caractères du texte : i =0 # indice du caractère en cours de lecture mot ="" # variable de travail : mot en cours de lecture for c in texte: c = c.lower # conversion de chaque caractère en minuscule if c in alpha: # car. alphab. => on est à l'intérieur d'un mot mot = mot + c else: # car. non-alphabétique => fin de mot if mot != "": # afin d'ignorer les car. non-alphabétiques successifs # pour chaque mot, on construit une liste d'indices : if dico.has_key(mot): # mot déjà répertorié : dico[mot].append(i) # ajout d'un indice à la liste else: # mot rencontré pour la 1e fois : dico[mot] =[i] # création de la liste d'indices mot ="" # préparer la lecture du mot suivant i = i+1 # indice du caractère suivant # Affichage du dictionnaire, en clair : for clef, valeur in dico.items: print clef, ":", valeur </syntaxhighlight> </li> </ol> </div> == Contrôle du flux d'exécution à l'aide d'un dictionnaire == Il arrive fréquemment que l'on ait à diriger l'exécution d'un programme dans différentes directions, en fonction de la valeur prise par une variable. Vous pouvez bien évidemment traiter ce problème à l'aide d'une série d'instructions <code>if - elif - else</code> , mais cela peut devenir assez lourd et inélégant si vous avez affaire à un grand nombre de possibilités. Exemple : <syntaxhighlight lang=python> materiau = raw_input("Choisissez le matériau : ") if materiau == 'fer': fonctionA elif materiau == 'bois': fonctionC elif materiau == 'cuivre': fonctionB elif materiau == 'pierre': fonctionD elif ... etc ... </syntaxhighlight> Les langages de programmation proposent souvent des instructions spécifiques pour traiter ce genre de problème, telles les instructions <code>switch</code> ou <code>case</code> du C ou du Pascal. Python n'en propose aucune, mais vous pouvez vous tirer d'affaire dans bien des cas à l'aide d'une liste, ou mieux encore à l'aide d'un dictionnaire. Exemple : <syntaxhighlight lang="python"> materiau = raw_input("Choisissez le matériau : ") dico = {'fer':fonctionA, 'bois':fonctionC, 'cuivre':fonctionB, 'pierre':fonctionD, ... etc ...} dico[materiau] </syntaxhighlight> Les deux instructions ci-dessus pourraient être condensées en une seule, mais nous les laissons séparées pour bien détailler le mécanisme : * La première instruction définit un dictionnaire dico dans lequel les clés sont les différentes possibilités pour la variable <code>materiau</code>, et les valeurs, les noms des fonctions à invoquer en correspondance. Notez bien qu'il s'agit seulement des noms de ces fonctions, qu'il ne faut surtout pas faire suivre de parenthèses dans ce cas (Sinon Python exécuterait chacune de ces fonctions au moment de la création du dictionnaire). * La seconde instruction invoque la fonction correspondant au choix opéré à l'aide de la variable <code>materiau</code>. Le nom de la fonction est extrait du dictionnaire à l'aide de la clé, puis associé à une paire de parenthèses. Python reconnaît alors un appel de fonction tout à fait classique et l'exécute. Vous pouvez encore améliorer la technique ci-dessus en remplaçant cette instruction par sa variante ci-dessous, qui fait appel à la méthode <code>get</code> afin de prévoir le cas où la clé demandée n'existerait pas dans le dictionnaire (vous obtenez de cette façon l'équivalent d'une instruction <code>else</code> terminant une longue série de <code>elif</code>) : <syntaxhighlight lang=python> dico.get(materiau, fonctAutre) </syntaxhighlight> Lorsque la la valeur de la variable "materiau "ne correspond à aucune clé du dictionnaire, c'est la fonction <code>fonctAutre</code> qui est invoquée. == Différences entre deux dictionnaires == Par exemple pour savoir quels sont les éléments importés<ref>https://stackoverflow.com/questions/32815640/how-to-get-the-difference-between-two-dictionaries-in-python</ref> : <syntaxhighlight lang="python"> d1 = locals.copy import pywikibot d2 = locals print(set(d2) - set(d1)) </syntaxhighlight> == Références == <div class="references-small" style="column-count:1; -moz-column-count:1; -webkit-column-count:1;"><references group=""></references></div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> =Dates= == Module datetime == Les dates se manipulent à l'aide du module <code>datetime</code><ref>https://docs.python.org/2/library/datetime.html</ref>. == Syntaxe == <syntaxhighlight lang=python> >>> import datetime >>> maDate = datetime.datetime.now >>> print (maDate) 2017-04-22 01:49:41.230711 >>> </syntaxhighlight> Impossible de tronquer une date complète comme une chaine de caractères, il faut utiliser les fonctions du module : <syntaxhighlight lang=python> >>> print (maDate.year) 2017 >>> print (maDate.month) 4 >>> print (maDate.day) 22 >>> print (maDate.hour) 1 >>> print (maDate.minute) 49 >>> print (maDate.second) 41 >>> print (maDate.microsecond) 230711 >>> </syntaxhighlight> Les variables de ce type sont très faciles à additionner et soustraire : <syntaxhighlight lang=python> >>> maDateDeFin = datetime.datetime.now >>> print (maDateDeFin - maDate) 0:04:38.266647 </syntaxhighlight> == Références == <div class="references-small" style="column-count:1; -moz-column-count:1; -webkit-column-count:1;"><references group=""></references></div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> =Ensembles= == Définition == En Python, les [[w:fr:Ensemble (informatique)|ensembles]] sont définis par le mot "<code>set</code>"<ref>https://docs.python.org/2/library/stdtypes.html#set</ref> depuis Python 2.3, d'abord en important le module du même nom, puis depuis nativement Python 2.6, avec "<code>frozenset</code>". Un ensemble est une collection non ordonnée d'objets, contrairement aux séquences comme les listes et les tuples dans lesquels chaque élément est indexé. Un ensemble ne peut pas contenir de doublon : on ne peut y trouver des éléments que zéro ou une fois. Tous les membres d'un ensemble doivent être [[wikt:hachable|hachable]], comme les clés des dictionnaires. À titre d'exemple, les [[wikt:scalaire|scalaire]]s comme les entiers, flottants, tuples, et chaînes sont hachables ; par contre les dictionnaires, listes, et ensembles ne le sont pas. Exemple : <syntaxhighlight lang="python"> set1 = set # Nouvel ensemble vide set1.add("cat") # Ajout d'un membre set1.update(["dog", "mouse"]) # Ajout de plusieurs membres if "cat" in set1: # Recherche d'un membre set1.remove("cat") # Retrait d'un membre #set1.remove("elephant") - Erreur de retrait d'un membre introuvable set1.discard("elephant") # Aucune erreur de retrait d'un membre introuvable print(set1) # Affichage d'un ensemble for item in set1: # Itération pour chaque élément print(item) print("Item count:", len(set1)) # Compte des éléments #1stitem = set1[0] # Erreur d'index introuvable isempty = len(set1) == 0 # Test si l'ensemble est vide set1 = set(["cat", "dog"]) # Initialisation de l'ensemble depuis une liste de membre set2 = set(["dog", "mouse"]) set3 = set1 & set2 # Intersection set4 = set1 | set2 # Union set5 = set1 - set3 # Différence set6 = set1 ^ set2 # Différence symétrique issubset = set1 <= set2 # Test de sous-ensemble issuperset = set1 >= set2 # Test de sur-ensemble set7 = set1.copy # Copie d'un ensemble set7.remove("cat") set8 = set1.copy set8.clear # Effacement d'un ensemble print(set1, set2, set3, set4, set5, set6, set7, set8, issubset, issuperset) </syntaxhighlight> ==Construction d'ensembles == Une première méthode consiste à fournir un objet séquentiel en paramètre : <syntaxhighlight lang="python"> >>> set([0, 1, 2, 3]) set([0, 1, 2, 3]) >>> set("obtuse") set(['b', 'e', 'o', 's', 'u', 't']) </syntaxhighlight> Ajout de chaque membre un par un : <syntaxhighlight lang="python"> >>> s = set([12, 26, 54]) >>> s.add(32) >>> s set([32, 26, 12, 54]) </syntaxhighlight> Ajout de groupes de membres : <syntaxhighlight lang="python"> >>> s.update([26, 12, 9, 14]) >>> s set([32, 9, 12, 14, 54, 26]) </syntaxhighlight> <div class="remarque">&nbsp;si on ajoute un doublon avec "add" ou "update", cela n'a aucun effet.</div> Ajout par copie d'un autre ensemble : <syntaxhighlight lang="python"> >>> s2 = s.copy >>> s2 set([32, 9, 12, 14, 54, 26]) </syntaxhighlight> == Recherche de membre == Pour chercher si un élément existe dans un ensemble, on utilise "in" : <syntaxhighlight lang="python"> >>> 32 in s True >>> 6 in s False >>> 6 not in s True </syntaxhighlight> Si un sous-ensemble existe dans un ensemble, c'est "issubset" : <syntaxhighlight lang="python"> >>> s.issubset(set([32, 8, 9, 12, 14, -4, 54, 26, 19])) True </syntaxhighlight> Si un sur-ensemble contient un ensemble, c'est "issuperset" : <syntaxhighlight lang="python"> >>> s.issuperset(set([9, 12])) True # Équivalent à : >>> s.issuperset([9, 12]) # Équivalent à : >>> s >= [9, 12] </syntaxhighlight> == Retrait de membre == Il existe quatre fonctions pour retirer des membres à un ensemble : # "pop" : retire un membre non précisé. # "remove" : retire le membre existant précisé. # "discard" : retire un membre précisé. # "clear" : retire tous les éléments. <syntaxhighlight lang="python"> >>> s = set([1,2,3,4,5,6]) >>> s.pop 1 >>> s set([2,3,4,5,6]) >>> s.remove(3) >>> s set([2,4,5,6]) >>> s.remove(9) Traceback (most recent call last): File "<stdin>", line 1, in ? KeyError: 9 >>> s.clear >>> s set() </syntaxhighlight> == Itération des ensembles == Les éléments n'étant pas ordonnés, il n'y a qu'une boucle possible : <syntaxhighlight lang="python"> >>> s = set("blerg") >>> for n in s: ... print n, ... r b e l g </syntaxhighlight> == Opérations sur les ensembles == Python offre les mêmes opérations sur les ensembles qu'en mathématiques, applicables par soit par des opérateurs, soit par des fonctions équivalentes. Les fonctions dont le nom se termine par <code>_update</code> modifie l'ensemble qui devient le résultat et ne retourne rien au lieu de retourner le résultat. === Intersection === [[Image:Venn0001.svg|thumb|L'intersection des deux cercles apparaît en rouge.]] Les éléments communs à deux ensembles. <syntaxhighlight lang="python"> >>> s1 = set([4, 6, 9]) >>> s2 = set([1, 6, 8]) >>> s1.intersection(s2) set([6]) >>> s1 & s2 set([6]) >>> s1.intersection_update(s2) >>> s1 set([6]) </syntaxhighlight> === Union === [[Image:Venn0111.svg|thumb|L'union des deux cercles apparaît en rouge.]] Somme des éléments de deux ensembles. <syntaxhighlight lang="python"> >>> s1 = set([4, 6, 9]) >>> s2 = set([1, 6, 8]) >>> s1.union(s2) set([1, 4, 6, 8, 9]) >>> s1 | s2 set([1, 4, 6, 8, 9]) </syntaxhighlight> === Différence symétrique === [[Image:Venn0110.svg|thumb|La différence symétrique des deux cercles apparaît en rouge.]] <nowiki>Éléments contenu dans un seul ensemble à la fois, parmi deux. autrement : [ l'union des deux #set] -[l'intersection]</nowiki> <syntaxhighlight lang="python"> >>> s1 = set([4, 6, 9]) >>> s2 = set([1, 6, 8]) >>> s1.symmetric_difference(s2) set([8, 1, 4, 9]) >>> s1 ^ s2 set([8, 1, 4, 9]) >>> s1.symmetric_difference_update(s2) >>> s1 set([8, 1, 4, 9]) </syntaxhighlight> === Différence === [[Image:Venn0100.svg|thumb|La différence asymétrique entre les deux cercles apparaît en rouge.]] Éléments non contenu dans un des deux ensembles. <syntaxhighlight lang="python"> >>> s1 = set([4, 6, 9]) >>> s2 = set([1, 6, 8]) >>> s1.difference(s2) set([9, 4]) >>> s1 - s2 set([9, 4]) >>> s1.difference_update(s2) >>> s1 set([9, 4]) </syntaxhighlight> == Opérations non binaires == Depuis Python 2.6, les fonctions vues précédemment acceptent plus de deux arguments : # .intersection # .union # .symmetric_difference # .difference. Un appel à plus de deux arguments est équivalent à des appels enchaînés à deux arguments, ou un argument dans le cas d'un appel de méthode sur une instance. Exemple : <syntaxhighlight lang="python"> >>> s1 = set([3, 6, 7, 9]) >>> s2 = set([6, 7, 9, 10]) >>> s3 = set([7, 9, 10, 11]) >>> set.intersection(s1, s2, s3) set([9, 7]) >>> set.intersection(s1, s2).intersection(s3) set([9, 7]) >>> s1.intersection(s2).intersection(s3) set([9, 7]) >>> s1.intersection(s2,s3) set([9, 7]) </syntaxhighlight> ==frozenset== Un "frozenset" (ensemble figé) se comporte comme un ensemble, sauf qu'il est [[wikt:immutable|immutable]], c'est-à-dire qu'une fois créé, on ne peut pas le mettre à jour. Il dispose donc des mêmes fonctions que le type "set", mais sans "add", "update", "pop", "remove", "discard" et "clear". De plus, ils sont hachables, ce qui leur permet de faire partie d'ensembles. <syntaxhighlight lang=python> >>> fs = frozenset([2, 3, 4]) >>> s1 = set([fs, 4, 5, 6]) >>> s1 set([4, frozenset([2, 3, 4]), 6, 5]) >>> fs.intersection(s1) frozenset([4]) >>> fs.add(6) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'frozenset' object has no attribute 'add' </syntaxhighlight> Les instructions suivantes montrent que les méthodes modificatrices sont absentes de la classe frozenset : <syntaxhighlight lang=python> >>> set(dir(set)) - set(dir(frozenset)) {'__iand__', 'pop', 'add', '__isub__', 'clear', '__ior__', 'discard', 'update', '__ixor__', 'intersection_update', 'difference_update', 'symmetric_difference_update', 'remove'} >>> set(dir(frozenset)) - set(dir(set)) set Exercices Créer un set {'cat', 1, 2, 3}, appelé "s". Créer un set {'c', 'a', 't', '1', '2', '3'}. Créer un frozen set {'cat', 1, 2, 3}, appelé "fs". Créer un set contenant {frozenset({'cat', 2, 3, 1})}. Références Python Tutorial, section "Data Structures", subsection "Sets" -- python.org Python Library Reference on Set Types -- python.org PEP 218 -- Adding a Built-In Set Object Type, python.org, a nice concise overview of the set type GFDL Vous avez la permission de copier, distribuer et/ou modifier ce document selon les termes de la licence de documentation libre GNU, version 1.2 ou plus récente publiée par la Free Software Foundation ; sans sections inaltérables, sans texte de première page de couverture et sans texte de dernière page de couverture.