Cours de Florent.

# Introduction à la programmation avec Python

## Introduction

Il est difficile d'écrire un cours à la page d'un langage de programmation comme python.
En effet, à l'instar du français qui n'est pas une langue morte, le python est en perpétuelle évolution.

Dans l'immédiat le python est dans la version majeure 3.
En général on indique une version mineure pour un logiciel ou un language après le numéro de la version majeure.
Une version récente est le python 3.10

[Tutoriel python3](https://docs.python.org/fr/3/tutorial/interpreter.html#invoking-the-interpreter)



## Quelques propriétés de python

La page wikipedia commence par beaucoup de jargon.

[Python sur wikipedia](https://fr.wikipedia.org/wiki/Python_(langage))


> Python (prononcé /pi.tɔ̃/) est un langage de programmation interprété, multiparadigme et multiplateformes. Il favorise la programmation impérative structurée, fonctionnelle et orientée objet. Il est doté d'un typage dynamique fort, d'une gestion automatique de la mémoire par ramasse-miettes et d'un système de gestion d'exceptions ; il est ainsi similaire à Perl, Ruby, Scheme, Smalltalk et Tcl.

Nous allons définir approximativement ces mots de jargon.

- [interprété (vs compilé)](http://www.france-ioi.org/algo/course.php?idChapter=561&idCourse=2368)
- impérative vs déclarative (au tableau) 
- structurée
- multiplateforme
- orientée objet
- typage dynamique
- ramasse-miettes
- gestion d'exception

## Prise en main

En général quand on connaît déjà un peu un langage, on se reporte au manuel.
Quand on ne le connais pas du tout, le plus simple est de prendre un tutoriel.

À la fin de ce cours il faut idéalement avoir digéré l'introduction informelle à Python de ce tutoriel.

[Tutoriel python3 intro informelle](https://docs.python.org/fr/3/tutorial/introduction.html)


## Exercices.

### Itérer sur un mot
Par défaut python cache de nombreux détails.
Ceci permet d'écrire du code plutôt court et plutôt lisible.
L'inconvénient c'est qu'il est plus difficile de savoir vraiment ce que Python fait pour un programmeur.
On va donc utiliser d'autres langages plus explicites si on recherche plus d'efficacité et de contrôle (par exemple le C). 

Dans le code ci-dessous, la boucle for va itérer sur les charactères du mot.

```python
voyelles="aeiouy"
for element in voyelles:
    print(element," ", end=' ')
print("\n")
```

Vous pouvez tester ce code, et par exemple le changer pour afficher des virgules entre chaque voyelle.

<details><summary>Fabriquer un exécutable</summary>
<p>

Si on souhaite lancer le programme en dehors de l'interpréteur, on peut le sauver dans un fichier et le passer en paramètre de la commande python3.

```bash
$ python3 0LoopOnWord.py 
```

On peut sous unix rendre un tel fichier exécutable et indiquer directement dans le code que le système doit utiliser la commande python3 en écrivant en haut du fichier

```bash
#! /usr/bin/python3
# -*- coding: utf-8 -*-
```
La seconde ligne indique le codage du fichier texte comme expliqué dans le tutoriel.

Si on veut rendre le fichier exécutable, on peut le faire probablement en cliquant dans l'explorateur de fichier, ou en ligne de commande dans le terminal avec chmod.

```bash
$ chmod +x 0LoopOnWord.py
```
Vous pouvez vérifier les droits en faisant.
```bash
$ ls -l
-rwxrwxr-x 1 madelaine madelaine 133 oct.  13 22:34 0LoopOnWord.py
```
Ceci donne le droit d'exécution à tout le monde.
Vous pouvez garder ces droits pour vous et votre groupe et les enlever aux autres (others, o pour faire court) en faisant

```bash
$ chmod o-x 0LoopOnWord.py
$ ls -l
-rwxrwxr-- 1 madelaine madelaine 133 oct.  13 22:34 0LoopOnWord.py
```
Puis les garder seulement pour vois en les enlevant au groupe (group, g pour faire court) en faisant
```bash
$ chmod g-x 0LoopOnWord.py
$ ls -l
-rw-rw-r-- 1 madelaine madelaine 133 oct.  13 22:34 0LoopOnWord.py
```
Dès que quelqu'un a les droits d'exécution il peut faire.
```bash
$ ./0LoopOnWord.py 
a   e   i   o   u   y


```
Notez le ./ avant la commande pour que bash trouve votre exécutable.
Sinon on obtient 
```bash
$ 0LoopOnWord.py 
0LoopOnWord.py : commande introuvable
```
Pourquoi?

De manière générale votre shell va chercher l'exécutable dans divers endroits, a priori comme indiqué par la variable d'environnement PATH
```bash
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
```
Le : sert de séparateur entre les chemins.

Comme bash cherche de gauche à droite, l'usage normal est d'aller du plus spécifique au plus général.
Ainsi vous pouvez ajouter le répertoire actuel (.) en changeant la variable d'environnement PATH comme ci-dessous.

```bash
$ PATH=.:$PATH
$ echo $PATH
.:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
```
Ceci permet de saisir maintenant
```bash
$ 0LoopOnWord.py 
a   e   i   o   u   y


```
</p>
</details>

### Itérer sur un mot

Aller lire le manuel [ici](https://docs.python.org/3/library/functions.html?highlight=ord#ord)

Changez le programme précédent pour afficher le code ascii des voyelles.


### Rot13

Le code de césar ou rot13 correspond à décaler de 13 lettres.
On va supposer que notre mot contient des lettres minuscules de a à z, ce qui correspond aux entiers 97 à 122

```
>>> ord('a')
97
>>> ord('z')
122
```
Le plus simple (pour un informaticien) consiste à décaler la valeur entre 0 et 25 en retranchant 97, puis de travailler modulo 26 (noté par %26 en python et dans de nombreux languages).
On peut ensuite appliquer la fonction inverse de ord qui s'appelle chr pour trouver la lettre.

```
>>> ((ord('y')-97))
24
>>> ((ord('y')-97))+13
37
>>> (((ord('y')-97))+13) %26
11
>>> ((((ord('y')-97))+13) %26)+97
108
>>> chr(((((ord('y')-97))+13) %26)+97)
'l'
```

Écrivez un programme 2Rot13.py qui transforme le contenu d'une variable message contenant une chaîne de charactère et l'affiche à l'écran en rot13.

### Fonction

Pour structurer notre programme et le rendre plus lisible ce qui évite les bugs et permet aux autres programmeurs de comprendre notre intention on va découper notre code en petite unité élémentaires qui
- prennent des paramètres en entrées
- retourne (pas toujours) une valeur
Ce sont les fonctions.

Par défaut en python il est recommandé de documenter la fonction directement dans le code.

Voici un exemple un peu compliqué tiré du tutoriel qui calcule la célèbre série de Fibonnacci jusqu'au nième terme.

```
def fib2(n):  # return Fibonacci series up to n
     """Return a list containing the Fibonacci series up to n."""
     result = []
     a, b = 0, 1
     while a < n:
         result.append(a)    # see below
         a, b = b, a+b
     return result
```

#### Exercice
Reprenez l'exercice rot13 mais en ajoutant une fonction carot13() qui permet de faire le décalage pour une lettre.
Par exemple carot13('y') retourne 'l' et carot13('l') retourne 'y'.

Dans un second temps écrivez une fonction marot13() qui s'applique à un mot et fait le décalage pour chaque lettre et retourne le mot correspondant en rot13.

Finalement testez en vérifiant en fin de fichier comme ceci.
```python
# test
print("test rot13")
print("abcdefghijklmnopqrstuvwxyz")
print(marot13("abcdefghijklmnopqrstuvwxyz"))
print(marot13(marot13("abcdefghijklmnopqrstuvwxyz")))
```
Ceci donnera en cas de succès

```bash
$ python3 ./3Rot13.py 
test rot13
abcdefghijklmnopqrstuvwxyz
nopqrstuvwxyzabcdefghijklm
abcdefghijklmnopqrstuvwxyz
```
### En laissant les espaces
    Le rot13 historique laisse les espaces puisqu'il faut qu'un geek averti puisse tout de même lire le rot13 à l'écran et ricaner en se complaisant de sa superiorité qui lui permet de lire le message "secret".

Sans vérification préalable carot13 devrait transformer les espaces en a
```
>>> chr(((((ord(' ')-97))+13) %26)+97)
'a'
```

Vous pouvez utiliser la méthode split pour séparer les mots selon les espaces.
```python
>>> "the lazy dog jumped over the quick brown fox".split()
['the', 'lazy', 'dog', 'jumped', 'over', 'the', 'quick', 'brown', 'fox']
```
La notation est un peu étrange, on écrit la chaîne de caractère puis un point puis split.
C'est parce que en fait une chaîne de caractère est un objet pour python et que split est une méthode de la classe de cet objet.
On en reparlera plus tard.
Vous pouvez imaginer qu'on a juste appliqué une fonction à la chaîne de caractère.
Le résultat est une liste de mots.

On peut joindre une liste de mot avec la méthode join
```python
>>> L="the lazy dog jumped over the quick brown fox".split()
>>> "XX".join(L)
'theXXlazyXXdogXXjumpedXXoverXXtheXXquickXXbrownXXfox'
>>> " ".join(L)
'the lazy dog jumped over the quick brown fox'
>>> 
```
On recommande d'utiliser l'élégat mécanisme de **liste en compréhension** pour transformer une liste de mots avec rot13.
```python
[marot13(mot) for mot in maListeDeMots]
```

### Divers Python
Le tutoriel de W3 school contient les mots réservés de python.
[voir ici](https://www.w3schools.com/python/python_ref_keywords.asp)

Plus généralement ce tutoriel donne des exemples simples et progressifs de plusieurs concepts.

- [les variables](https://www.w3schools.com/python/python_variables.asp)
- [les boucles]()
- [les fonctions]()


```python
+= #
```
