Modifications entre les versions 1 et 23 (s'étendant sur 22 versions)
Version 1 à la date du 2012-11-20 12:47:36
Taille: 433
Éditeur: iml138
Commentaire:
Version 23 à la date du 2012-11-21 13:09:05
Taille: 18044
Éditeur: 90
Commentaire:
Texte supprimé. Texte ajouté.
Ligne 1: Ligne 1:
## page was renamed from Supports/InitiationPython3
#acl Formateurs:read,write,revert All:read
Ligne 5: Ligne 8:
Le langage de programmation fixé comme référence pour cette année de
formation, est Python, en version 3. Ce premier TP a pour but de vous
donner des bases de programmation suffisantes pour transcrire
n’importe quel algorithme travaillant sur des types de données
simples : nombres, chaînes de caractères et listes. Il ne s’agit pas d’être
virtuose, mais simplement que le langage ne soit pas un obstacle à la mise en
pratique.

Si vous connaissez déjà bien Python, ne vous attardez bien sûr pas sur le début.
Le choix de l’environnement de développement (ici IDLE) n’est qu’une
suggestion : faites comme à la maison.

Si vous connaissez déjà un autre langage de programmation, c’est l’occasion
d’en découvrir un nouveau, peut-être assez différent.

Dans ces deux cas, la première partie ne devrait pas trop poser de problème, et
vous pourrez vous attaquer à un authentique TP de programmation en deuxième
partie.

Et si c’est votre premier contact avec la programmation, pas d’inquiétude, on avancera pas à pas.
La deuxième partie est tout à fait optionnelle à ce niveau.

<<TableOfContents()>>
Ligne 7: Ligne 34:
{{{#!wiki tip
Si ce n’est déjà fait, il faut bien sûr commencer par installer Python :
 * si vous travaillez sous Windows ou Mac, les fichiers nécessaires sont accessibles sur le site [[http://www.python.org/]] : choisir la dernière version stable (actuellement 3.3.0) ;
 * sous GNU/Linux, installez simplement les paquets python3 et idle3 en utilisant le gestionnaire de paquet de votre distribution.

Avec un peu de chance, ces instructions sont inutiles dans la salle informatique
du site de formation. :-)
}}}

Un programme Python est un simple fichier de texte qui contient les instructions
à faire exécuter par la machine, ou plutôt l’interpréteur Python. Par exemple :
{{{#!highlight python
def bonjour(nom):
    print("Bonjour "+nom+" !")

nom = input("Comment vous appelez-vous ? ")
bonjour(nom)
}}}
On pourrait
donc se contenter de taper ce code source dans un éditeur de texte (ce qui est
différent d’un logiciel de traitement de texte), puis le faire exécuter par
l’interpréteur. Mais l’interpréteur peut également être utilisé de manière
interactive. C’est ce que nous ferons pour les premiers pas qui suivent.

Lançons donc l’environnement graphique IDLE. On se retrouve devant une fenêtre
comme celle-ci :

{{attachment:IDLE.png}}

L’invite {{{>>>}}} nous… invite à taper des instructions Python.
Ce que nous allons nous empresser de faire.
Ligne 9: Ligne 68:
Lorsque vous tapez une instruction, l’interpréteur affiche la valeur
éventuellement produite.

Par exemple :
{{{#!highlight python
>>> 42
42
}}}
(j’ai tapé « {{{42}}} », puis fait « Entrée » et l’interpréteur a affiché {{{42}}}).

On peut bien sûr former des expressions arithmétiques plus compliquées.
Testez par exemple les expressions suivantes et essayez de deviner ce que ça
calcule, si possible avant de le taper :
{{{#!highlight python
21+21
32*(42+10)
2**3
2**4
2**5
2.5*2
2/3
1/1
2//3
13//6
13%6
1//1
}}}
Si vous connaissez Python 2, certains des résultats précédents vous ont
peut-être surpris. On les expliquera sur place.

Et si vous avez le moindre doute sur ce qui vient de se passer, il faut le dire !

{{{#!wiki tip
À tout moment, vous pouvez revenir sur une ligne précédente et appuyer sur
« Entrée » pour recopier automatiquement son contenu : pratique quand on a fait
une erreur de frappe ou quand on tape des lignes un peu répétitives.
}}}

Plus étonnant peut-être :
{{{#!highlight python
100**100
100**100-100**99
100.0**100
100.0**100-100**99
2**2**2
2**2**2**2
2**2**2**2**2 # C’est peut-être un peu risqué !
2**2**2**2**2**2 # À tous les coups ça plante…
}}}

{{{#!wiki tip
Si le programme a l’air bloqué, vous pouvez interrompre l’exécution
avec la combinaison de touches « `Ctrl+C` ».
}}}

{{{#!wiki important
À ce stade, que pouvez-vous dire de la manière dont Python 3 gère les nombres ?
}}}

==== Python comme calculatrice scientifique ====

On n’est bien sûr pas limités aux opérations arithmétiques. Python est en fait
un langage assez prisé dans le monde du calcul scientifique moderne, en
particulier parce qu’il fournit des bibliothèques de calcul aux fonctionnalités avancées.
Il n’en sera pas question ici, mais on peut déjà trouver pas mal de choses dans
la bibliothèque standard.

Essayez ce qui suit :
{{{#!highlight python
from math import * # On fait ici un peu de magie, qui sera expliquée plus tard dans l’année
pi
log(1)
log(e)
cos(pi/3)
log(1024,2)
}}}


=== Chaînes de caractères ===

Bien sûr Python n’est pas limité au calcul numérique : le cœur de
l’informatique moderne (disons à partir des années 70), ce sont les chaînes de
caractères. En Python, une chaîne littérale est indifféremment entourée d’apostrophes « `'` »
ou de guillemets anglais « `"` ».

Tentons un laconique :
{{{#!highlight python
'Bonjour.'
}}}
Notez que les apostrophes restent présentes dans la sortie : l’interpréteur
nous signale que nous avons bien construit une chaîne.

Pour afficher une chaîne, on utilise l’instruction `print` :
{{{#!highlight python
print('Bonjour.')
}}}
Vous voyez la différence ?

L’opération de base sur les chaînes est la concaténation :
{{{#!highlight python
'Bon' + 'jour.'
}}}
Oui, ça se note comme une somme.

On peut aussi calculer la longueur d’une chaîne :
{{{#!highlight python
len('Bon' + 'jour.')
}}}

Notez que Python 3 n’est pas inquiété par tous les caractères bizarres que vous
pourrez entrer :
{{{#!highlight python
print('Considérons la fonction φ : x ↦ x³.')
len('1 €')
}}}
(par contre, votre navigateur peut l’être).

La dernière ligne en étonnera peut-être certains.

Ligne 11: Ligne 190:
=== Travailler avec un environement de développement ===

=== Fonctions ===

=== Listes et chaînes ===
On a vu qu’un élément essentiel de l’écriture d’algorithmes est la possibilité
de stocker des informations intermédiaires dans des ''variables'' : cette
notion est omniprésente en programmation.

En Python, le nom d’une variable est nécessairement constitué de caractères alphanumériques,
plus éventuellement le caractère « souligné » `_`. Le premier caractère doit être une lettre.

Des exemples :
{{{
x
x1
ma_variable_preferee
}}}

L’affectation d’une valeur à une variable est notée par le signe d’égalité « `=` », un
choix mathématiquement regrettable mais assez répandu. Essayons :
{{{#!highlight python
x = 32
y = 52
somme = x+y
produit = x*y
}}}

On peut afficher une valeur numérique de la même manière qu’une chaîne :
{{{#!highlight python
print(somme)
print(produit)
}}}

Et on peut afficher plusieurs choses sur la même ligne :
{{{#!highlight python
print('x :',x,'y :',y,'Somme :',somme,'Produit :',produit)
}}}

Continuons :
{{{#!highlight python
x = -1
print('x :',x,'y :',y,'Somme :',somme,'Produit :',produit)
}}}

{{{#!wiki important
Quelles remarques pouvez-vous déjà faire sur l’utilisation des variables en Python ?
Pouvez-vous expliquer ce qui se passe ?
}}}

Continuons :
{{{#!highlight python
x = 'Ceci est une chaîne !'
print('x :',x,'y :',y,'Somme :',somme,'Produit :',produit)
}}}
Le résultat vous surprend peut-être : la variable `x` était d’abord un nombre,
voilà que c’est une chaîne. Pourtant, pas de message d’erreur !
On pourrait croire que Python ignore l’information de type. C’est plus subtil.
 
En Python, toute ``valeur`` a un type bien déterminé. D’ailleurs,
l’interpréteur peut nous le donner :
{{{#!highlight python
type(1)
type(0.5)
type('a')
type('un mot')
type('€uro')
}}}
Par contre les variables ne sont pas typées a priori : une variable n’est qu’un `nom`
auquel on peut associer temporairement une valeur, de type quelconque.
{{{#!highlight python
x=1
type(x)
x='a'
type(x)
}}}
En particulier, en Python, ''on ne déclare pas les variables''.

De plus, les opérations sont surchargées : on a vu que le `+` est défini entre
deux nombres ou entre deux chaînes, et que le type de retour pouvait être adapté.

Tentons :
{{{#!highlight python
print('Le résultat est '+42)
}}}
Que se passe-t-il ? Ce cas n’est pas prévu dans la définition de `print`.

Il est facile de convertir un nombre en la chaîne qui le représente, et réciproquement :
{{{#!highlight python
str(42)
int('100')
float('1')
}}}
On peut aussi forcer la conversion entre types de nombres de la même manière :
{{{#!highlight python
float(1)
int(100.0**100)
}}}

Une utilisation standard :
{{{#!highlight python
entree = input('Entrez un nombre entier N : ')
N = int(entree)
print('N² = '+str(N*N))
}}}

=== Booléens ===

Un dernier type de base, que nous n’avons pas encore croisé : les booléens.
C’est le type à deux valeurs : vrai et faux.
{{{#!highlight python
True
False
type(True)
}}}

On fabrique des booléens avec des tests :
{{{#!highlight python
1 > 0
1 < 0
1 == 0 # Attention, on double le signe = pour le distinguer de l’affectation
'a' = 'b'
'a' + 'a' == 'aa'
}}}
Et on peut les composer via les opérations booléennes `and`, `or`, `not` :
{{{#!highlight python
s = 'Bonjour.'
s == '' or len(s) > 2
}}}
Ligne 19: Ligne 317:
Jusque là, on a parlé des opérations de base du calcul.
Reste à introduire l’algorithmique à proprement parler.

Le branchement conditionnel prend la forme `if `''condition''`: `''instruction''.
Vous pouvez deviner ce que fait :
{{{#!highlight python
if x<0: x=-x
}}}
Si le branchement comprend une alternative, on utilise `else` :
{{{#!highlight python
if x<0: y=0
else: y=x
}}}
Si plusieurs instructions doivent suivre, on les met à la ligne '''''en respectant l’indentation''''' :
{{{#!highlight python
b = -b / 2
delta = b * b - a * c
if delta > 0:
 n = 2
 x1 = (b - sqrt(delta)) / a
 x2 = (b + sqrt(delta)) / a
else:
 if delta == 0:
  n = 1
  x = b/a
 else:
  n = 0
}}}
Cette convention trouble souvent les programmeurs de langages comme C ou Java.
Elle a pourtant le mérite d’être concise, lisible et d’éviter la frappe de
délimiteurs.

La structure `else: if:` imbriquée, peut-être abrégée en `elif`, ce qui
économise un niveau d’indentation :
{{{#!highlight python
if delta > 0:
 n = 2
 x1 = (b - sqrt(delta)) / a
 x2 = (b + sqrt(delta)) / a
elif delta == 0:
 n = 1
 x = b/a
else:
 n = 0
}}}

La boucle ''tant que'' s’écrit naturellement sur le même modèle
`while `''condition''`:
{{{#!highlight python
n = 0
while n<10:
 print(n)
 n = n+1
}}}

=== Fonctions et procédures ===

La programmation ne se réduit pas à l’algorithmique : il est essentiel de
pouvoir faire référence à des morceaux de programmes déjà écrits, sans devoir
les recopier ! C’est le rôle des procédures (des suites d’instructions
auxquelles ont donne un nom) et des fonctions (la même chose, mais qui renvoie
un résultat).

En Python, on les introduit au moyen de la construction `def`:

{{{#!highlight python
def f (x1, x2, ...):
 ... des instructions ...
 return resultat
}}}
définit une nouvelle fonction qui, partant des valeurs initiales
de `x1, x2, ...` effectue les instructions requises, et renvoie
la valeur de l’expression `resultat`. Si on n’utilise pas l’instruction
`return` finale, ça fonctionne aussi sauf que rien n’est renvoyé (cas d’une
procédure).

Exemples :
{{{#!highlight python
def discriminant(a,b,c):
 return b * b - a * c

def resout (a,b,c):
 b = -b / 2
 delta = discriminant(a,b,c)
 if delta > 0:
  n = 2
  x = (b - sqrt(delta)) / a
  y = (b + sqrt(delta)) / a
 elif delta == 0:
  n = 1
  x = b/a
 else:
  n = 0
 print('Nombre de solutions : ' + str(n) + '.')
 if n > 0:
  print(' x = ' + str(x))
 if n == 2:
  print(' y = ' + str(y))
}}}

Essayez la chose suivante :
{{{#!highlight python
def incremente(a):
 a = a+1
 print('Nouvelle valeur de a : '+str(a))

a = 1
incremente(a)
print(a)
}}}

{{{#!wiki important
Que se passe-t-il ?
Que pouvez-vous dire sur la ''portée'' des variables en Python ?
Quelles autres expériences proposez-vous pour mieux comprendre ?
}}}


=== Listes, chaînes, n-uplets ===

On a déjà décrit le cœur algorithmique, les opérations sur les types de base et
le mécanisme d’affectation des variables.

Légitimement, on pourrait s’arrêter là : on a déjà un modèle de calcul complet,
(en un sens qui sera formalisé l’année prochaine).

Mais Python, comme tout langage contemporain, nous permet de composer ces types de base
en introduisant des types dits séquentiels : listes et n-uplets. Ceux-ci
rassemblent un nombre quelconque de valeurs au sein d’un même objet composé.
On forme un n-uplet avec des parenthèses :
{{{#!highlight python
z = (1,2,3)
}}}
une liste avec des crochets :
{{{#!highlight python
l = ['a','b','c']
}}}
On accède aux éléments d’une séquence avec les crochets :
{{{#!highlight python
print(z[1])
print(l[0])
print(l[1])
print(l[2])
print(l[3])
}}}
Que remarquez-vous ?

On peut concaténer les séquences avec le `+`, comme dans :
{{{#!highlight python
l = l + ['d']
}}}

La différence entre les deux types, c’est qu’on peut changer les éléments d’une liste,
mais pas ceux d’un n-uplet :
{{{#!highlight python
l[0] = 'A'
z[0] = '0'
}}}
On dit que les éléments d’une liste sont ''mutables''.

En fait, les chaînes de caractères sont en partie de la même nature que les n-uplets :
ce sont des suites… de caractères. Et on ne peut pas les changer.
{{{#!highlight python
s = 'Bonjour.'
s[0]
s[0]='b'
}}}

La boucle `for` de Python permet de répéter une suite d’instruction pour chacun
des éléments d’une séquence. Par exemple :
{{{#!highlight python
for k in [1,2,3]:
 print(k)
}}}

En fait, on peut librement mélanger les types au sein d’une séquence :
{{{#!highlight python
for k in [1,'a',100.0**.5]:
 print(k)
}}}

Et on peut même les imbriquer :
{{{#!highlight python
def mat22 (a,b,c,d):
 return((a,b),(c,d))
M=mat22(1,2,3,4)
M[1][0]
def affiche22 (M):
 for l in M:
  print l
affiche22(M)
}}}

La fonction `range`, bien utile, permet de générer une valeur qui se comporte comme
une liste d’entiers consécutifs. Essayez-la :
{{{#!highlight python
for i in range(10):
 print i
for i in range(1,10):
 print i
}}}
Notez que certains arguments des fonctions peuvent être optionnels. Pour
l’instant, on s’en tiendra à l’explication « magique ».

=== Premier exercice ===

Écrivez une fonction :
{{{#!highlight python
def renverse(entree):
 ...
 return sortie
}}}
qui prend en argument une chaîne `entree` et renvoie la chaîne
renversée, c’est-à-dire que `renverse('abcde')` doit renvoyer (et pas afficher) `'edcba'`.

Si vous êtes arrivés jusque là, vous avez fait le tour d’à peu près tout ce qui
est nécessaire pour couvrir les besoins du programmeur/algorithmicien généraliste
au quotidien.

Bravo !
Ligne 21: Ligne 540:
Le sujet de TP à proprement parler est en fait beaucoup plus court que l’introduction,
puisqu’il suppose une certaine autonomie.
Ligne 23: Ligne 545:
Écrivez une fonction :
{{{#!highlight python
def cesar(message,cle):
 ...
 return code
}}}
qui renvoie le code du `message`, suivant le chiffre de César paramétré par
l’entier `cle`. Pour mémoire, cela signifie que chaque lettre du `message` est
remplacée par la lettre qui se trouve `cle` « cases » plus loin dans
l’alphabet, quitte à revenir au début si on a atteint la fin de l’alphabet.

On pourra d’abord se contenter de transformer les lettres de l’alphabet latin,
et on laissera les autres caractères inchangés.

Deux outils cruciaux :
 * la fonction `ord`, qui renvoie le numéro d’un caractère (et on admet que les lettres ont des codes consécutifs) ;
 * la fonction `chr`, inverse de la précédente.

N’hésitez bien sûr pas à définir des fonctions auxiliaires pour décomposer le travail.
Elles pourront aussi être utiles pour la suite.

Faut-il écrire une autre fonction pour le décodage ?
Ligne 25: Ligne 570:
=== Un peu de sucre ? === Le chiffre de Vigenère généralise celui de César : la clé est maintenant un mot.
Dans cette clé :
 * la lettre `A` représente un décalage de 0,
 * la lettre `B` représente un décalage de 1,
 * la lettre `C` représente un décalage de 2,
 * …
L’idée du code est la suivante :
 * on décale la première lettre du message d’après la première lettre de la clé ;
 * on décale la deuxième lettre du message d’après la deuxième lettre de la clé ;
 * …
 * quand on a épuisé la clé, on revient à sa première lettre…
 * …

Écrivez des fonctions :
{{{#!highlight python
def vigenere(message,cle):
 ...
 return code
}}}
et
{{{#!highlight python
def devigenere(code,cle):
 ...
 return message
}}}
qui réalisent le codage et le décodage.

=== Pour aller plus loin ===

Le sujet du TP de rentrée du niveau 2 propose une méthode de cryptanalyse du
chiffre de Vigenère, basée sur la détection de motifs répétés et le calcul
de l’indice de coïncidence. Le sujet est disponible en ligne sur [[http://isn.irem.univ-mrs.fr/formation/]].

1B0 : TP d’initiation à Python 3

Initiation à Python 3

Le langage de programmation fixé comme référence pour cette année de formation, est Python, en version 3. Ce premier TP a pour but de vous donner des bases de programmation suffisantes pour transcrire n’importe quel algorithme travaillant sur des types de données simples : nombres, chaînes de caractères et listes. Il ne s’agit pas d’être virtuose, mais simplement que le langage ne soit pas un obstacle à la mise en pratique.

Si vous connaissez déjà bien Python, ne vous attardez bien sûr pas sur le début. Le choix de l’environnement de développement (ici IDLE) n’est qu’une suggestion : faites comme à la maison.

Si vous connaissez déjà un autre langage de programmation, c’est l’occasion d’en découvrir un nouveau, peut-être assez différent.

Dans ces deux cas, la première partie ne devrait pas trop poser de problème, et vous pourrez vous attaquer à un authentique TP de programmation en deuxième partie.

Et si c’est votre premier contact avec la programmation, pas d’inquiétude, on avancera pas à pas. La deuxième partie est tout à fait optionnelle à ce niveau.

Lancer un interpréteur

Si ce n’est déjà fait, il faut bien sûr commencer par installer Python :

  • si vous travaillez sous Windows ou Mac, les fichiers nécessaires sont accessibles sur le site http://www.python.org/ : choisir la dernière version stable (actuellement 3.3.0) ;

  • sous GNU/Linux, installez simplement les paquets python3 et idle3 en utilisant le gestionnaire de paquet de votre distribution.

Avec un peu de chance, ces instructions sont inutiles dans la salle informatique du site de formation. :-)

Un programme Python est un simple fichier de texte qui contient les instructions à faire exécuter par la machine, ou plutôt l’interpréteur Python. Par exemple :

   1 def bonjour(nom):
   2     print("Bonjour "+nom+" !")
   3 
   4 nom = input("Comment vous appelez-vous ? ")
   5 bonjour(nom)

On pourrait donc se contenter de taper ce code source dans un éditeur de texte (ce qui est différent d’un logiciel de traitement de texte), puis le faire exécuter par l’interpréteur. Mais l’interpréteur peut également être utilisé de manière interactive. C’est ce que nous ferons pour les premiers pas qui suivent.

Lançons donc l’environnement graphique IDLE. On se retrouve devant une fenêtre comme celle-ci :

IDLE.png

L’invite >>> nous… invite à taper des instructions Python. Ce que nous allons nous empresser de faire.

Python comme calculatrice

Lorsque vous tapez une instruction, l’interpréteur affiche la valeur éventuellement produite.

Par exemple :

   1 >>> 42
   2 42

(j’ai tapé « 42 », puis fait « Entrée » et l’interpréteur a affiché 42).

On peut bien sûr former des expressions arithmétiques plus compliquées. Testez par exemple les expressions suivantes et essayez de deviner ce que ça calcule, si possible avant de le taper :

   1 21+21
   2 32*(42+10)
   3 2**3
   4 2**4
   5 2**5
   6 2.5*2
   7 2/3
   8 1/1
   9 2//3
  10 13//6
  11 13%6
  12 1//1

Si vous connaissez Python 2, certains des résultats précédents vous ont peut-être surpris. On les expliquera sur place.

Et si vous avez le moindre doute sur ce qui vient de se passer, il faut le dire !

À tout moment, vous pouvez revenir sur une ligne précédente et appuyer sur « Entrée » pour recopier automatiquement son contenu : pratique quand on a fait une erreur de frappe ou quand on tape des lignes un peu répétitives.

Plus étonnant peut-être :

   1 100**100
   2 100**100-100**99
   3 100.0**100
   4 100.0**100-100**99
   5 2**2**2
   6 2**2**2**2
   7 2**2**2**2**2 # C’est peut-être un peu risqué !
   8 2**2**2**2**2**2 # À tous les coups ça plante…

Si le programme a l’air bloqué, vous pouvez interrompre l’exécution avec la combinaison de touches « Ctrl+C ».

À ce stade, que pouvez-vous dire de la manière dont Python 3 gère les nombres ?

Python comme calculatrice scientifique

On n’est bien sûr pas limités aux opérations arithmétiques. Python est en fait un langage assez prisé dans le monde du calcul scientifique moderne, en particulier parce qu’il fournit des bibliothèques de calcul aux fonctionnalités avancées. Il n’en sera pas question ici, mais on peut déjà trouver pas mal de choses dans la bibliothèque standard.

Essayez ce qui suit :

   1 from math import * # On fait ici un peu de magie, qui sera expliquée plus tard dans l’année
   2 pi
   3 log(1)
   4 log(e)
   5 cos(pi/3)
   6 log(1024,2)

Chaînes de caractères

Bien sûr Python n’est pas limité au calcul numérique : le cœur de l’informatique moderne (disons à partir des années 70), ce sont les chaînes de caractères. En Python, une chaîne littérale est indifféremment entourée d’apostrophes « ' » ou de guillemets anglais « " ».

Tentons un laconique :

   1 'Bonjour.'

Notez que les apostrophes restent présentes dans la sortie : l’interpréteur nous signale que nous avons bien construit une chaîne.

Pour afficher une chaîne, on utilise l’instruction print :

   1 print('Bonjour.')

Vous voyez la différence ?

L’opération de base sur les chaînes est la concaténation :

   1 'Bon' + 'jour.'

Oui, ça se note comme une somme.

On peut aussi calculer la longueur d’une chaîne :

   1 len('Bon' + 'jour.')

Notez que Python 3 n’est pas inquiété par tous les caractères bizarres que vous pourrez entrer :

   1 print('Considérons la fonction φ : x ↦ x³.')
   2 len('1 €')

(par contre, votre navigateur peut l’être).

La dernière ligne en étonnera peut-être certains.

Variables et types

On a vu qu’un élément essentiel de l’écriture d’algorithmes est la possibilité de stocker des informations intermédiaires dans des variables : cette notion est omniprésente en programmation.

En Python, le nom d’une variable est nécessairement constitué de caractères alphanumériques, plus éventuellement le caractère « souligné » _. Le premier caractère doit être une lettre.

Des exemples :

x
x1
ma_variable_preferee

L’affectation d’une valeur à une variable est notée par le signe d’égalité « = », un choix mathématiquement regrettable mais assez répandu. Essayons :

   1 x = 32
   2 y = 52
   3 somme = x+y
   4 produit = x*y

On peut afficher une valeur numérique de la même manière qu’une chaîne :

   1 print(somme)
   2 print(produit)

Et on peut afficher plusieurs choses sur la même ligne :

   1 print('x :',x,'y :',y,'Somme :',somme,'Produit :',produit)

Continuons :

   1 x = -1
   2 print('x :',x,'y :',y,'Somme :',somme,'Produit :',produit)

Quelles remarques pouvez-vous déjà faire sur l’utilisation des variables en Python ? Pouvez-vous expliquer ce qui se passe ?

Continuons :

   1 x = 'Ceci est une chaîne !'
   2 print('x :',x,'y :',y,'Somme :',somme,'Produit :',produit)

Le résultat vous surprend peut-être : la variable x était d’abord un nombre, voilà que c’est une chaîne. Pourtant, pas de message d’erreur ! On pourrait croire que Python ignore l’information de type. C’est plus subtil.

En Python, toute valeur a un type bien déterminé. D’ailleurs, l’interpréteur peut nous le donner :

   1 type(1)
   2 type(0.5)
   3 type('a')
   4 type('un mot')
   5 type('€uro')

Par contre les variables ne sont pas typées a priori : une variable n’est qu’un nom auquel on peut associer temporairement une valeur, de type quelconque.

   1 x=1
   2 type(x)
   3 x='a'
   4 type(x)

En particulier, en Python, on ne déclare pas les variables.

De plus, les opérations sont surchargées : on a vu que le + est défini entre deux nombres ou entre deux chaînes, et que le type de retour pouvait être adapté.

Tentons :

   1 print('Le résultat est '+42)

Que se passe-t-il ? Ce cas n’est pas prévu dans la définition de print.

Il est facile de convertir un nombre en la chaîne qui le représente, et réciproquement :

   1 str(42)
   2 int('100')
   3 float('1')

On peut aussi forcer la conversion entre types de nombres de la même manière :

   1 float(1)
   2 int(100.0**100)

Une utilisation standard :

   1 entree = input('Entrez un nombre entier N : ')
   2 N = int(entree)
   3 print('N² = '+str(N*N))

Booléens

Un dernier type de base, que nous n’avons pas encore croisé : les booléens. C’est le type à deux valeurs : vrai et faux.

   1 True
   2 False
   3 type(True)

On fabrique des booléens avec des tests :

   1 1 > 0
   2 1 < 0
   3 1 == 0 # Attention, on double le signe = pour le distinguer de l’affectation
   4 'a' = 'b'
   5 'a' + 'a' == 'aa'

Et on peut les composer via les opérations booléennes and, or, not :

   1 s = 'Bonjour.'
   2 s == '' or len(s) > 2 

Algorithmique de base

Jusque là, on a parlé des opérations de base du calcul. Reste à introduire l’algorithmique à proprement parler.

Le branchement conditionnel prend la forme if conditioninstruction. Vous pouvez deviner ce que fait :

   1 if x<0: x=-x

Si le branchement comprend une alternative, on utilise else :

   1 if x<0: y=0 
   2 else: y=x

Si plusieurs instructions doivent suivre, on les met à la ligne en respectant l’indentation :

   1 b = -b / 2
   2 delta = b * b - a * c
   3 if delta > 0:
   4         n  = 2
   5         x1 = (b - sqrt(delta)) / a
   6         x2 = (b + sqrt(delta)) / a
   7 else: 
   8         if delta == 0:
   9                 n  = 1
  10                 x  = b/a
  11         else:
  12                 n = 0

Cette convention trouble souvent les programmeurs de langages comme C ou Java. Elle a pourtant le mérite d’être concise, lisible et d’éviter la frappe de délimiteurs.

La structure else: if: imbriquée, peut-être abrégée en elif, ce qui économise un niveau d’indentation :

   1 if delta > 0:
   2         n  = 2
   3         x1 = (b - sqrt(delta)) / a
   4         x2 = (b + sqrt(delta)) / a
   5 elif delta == 0:
   6         n  = 1
   7         x  = b/a
   8 else:
   9         n = 0

La boucle tant que s’écrit naturellement sur le même modèle while condition`:

   1 n = 0
   2 while n<10:
   3         print(n)
   4         n = n+1

Fonctions et procédures

La programmation ne se réduit pas à l’algorithmique : il est essentiel de pouvoir faire référence à des morceaux de programmes déjà écrits, sans devoir les recopier ! C’est le rôle des procédures (des suites d’instructions auxquelles ont donne un nom) et des fonctions (la même chose, mais qui renvoie un résultat).

En Python, on les introduit au moyen de la construction def:

   1 def f (x1, x2, ...):
   2         ... des instructions ...
   3         return resultat

définit une nouvelle fonction qui, partant des valeurs initiales de x1, x2, ... effectue les instructions requises, et renvoie la valeur de l’expression resultat. Si on n’utilise pas l’instruction return finale, ça fonctionne aussi sauf que rien n’est renvoyé (cas d’une procédure).

Exemples :

   1 def discriminant(a,b,c):
   2         return b * b - a * c
   3 
   4 def resout (a,b,c):
   5         b = -b / 2
   6         delta = discriminant(a,b,c)
   7         if delta > 0:
   8                 n  = 2
   9                 x = (b - sqrt(delta)) / a
  10                 y = (b + sqrt(delta)) / a
  11         elif delta == 0:
  12                 n  = 1
  13                 x  = b/a
  14         else:
  15                 n = 0
  16         print('Nombre de solutions : ' + str(n) + '.')
  17         if n > 0:
  18                 print('  x = ' + str(x))
  19         if n == 2:
  20                 print('  y = ' + str(y))

Essayez la chose suivante :

   1 def incremente(a):
   2         a = a+1
   3         print('Nouvelle valeur de a : '+str(a))
   4 
   5 a = 1
   6 incremente(a)
   7 print(a)

Que se passe-t-il ? Que pouvez-vous dire sur la portée des variables en Python ? Quelles autres expériences proposez-vous pour mieux comprendre ?

Listes, chaînes, n-uplets

On a déjà décrit le cœur algorithmique, les opérations sur les types de base et le mécanisme d’affectation des variables.

Légitimement, on pourrait s’arrêter là : on a déjà un modèle de calcul complet, (en un sens qui sera formalisé l’année prochaine).

Mais Python, comme tout langage contemporain, nous permet de composer ces types de base en introduisant des types dits séquentiels : listes et n-uplets. Ceux-ci rassemblent un nombre quelconque de valeurs au sein d’un même objet composé. On forme un n-uplet avec des parenthèses :

   1 z = (1,2,3)

une liste avec des crochets :

   1 l = ['a','b','c']

On accède aux éléments d’une séquence avec les crochets :

   1 print(z[1])
   2 print(l[0])
   3 print(l[1])
   4 print(l[2])
   5 print(l[3])

Que remarquez-vous ?

On peut concaténer les séquences avec le +, comme dans :

   1 l = l + ['d']

La différence entre les deux types, c’est qu’on peut changer les éléments d’une liste, mais pas ceux d’un n-uplet :

   1 l[0] = 'A'
   2 z[0] = '0'

On dit que les éléments d’une liste sont mutables.

En fait, les chaînes de caractères sont en partie de la même nature que les n-uplets : ce sont des suites… de caractères. Et on ne peut pas les changer.

   1 s = 'Bonjour.'
   2 s[0]
   3 s[0]='b'

La boucle for de Python permet de répéter une suite d’instruction pour chacun des éléments d’une séquence. Par exemple :

   1 for k in [1,2,3]:
   2         print(k)        

En fait, on peut librement mélanger les types au sein d’une séquence :

   1 for k in [1,'a',100.0**.5]:
   2         print(k)        

Et on peut même les imbriquer :

   1 def mat22 (a,b,c,d):
   2         return((a,b),(c,d))
   3 M=mat22(1,2,3,4)
   4 M[1][0]
   5 def affiche22 (M):
   6         for l in M:
   7                 print l
   8 affiche22(M)

La fonction range, bien utile, permet de générer une valeur qui se comporte comme une liste d’entiers consécutifs. Essayez-la :

   1 for i in range(10):
   2         print i
   3 for i in range(1,10):
   4         print i

Notez que certains arguments des fonctions peuvent être optionnels. Pour l’instant, on s’en tiendra à l’explication « magique ».

Premier exercice

Écrivez une fonction :

   1 def renverse(entree):
   2         ...
   3         return sortie

qui prend en argument une chaîne entree et renvoie la chaîne renversée, c’est-à-dire que renverse('abcde') doit renvoyer (et pas afficher) 'edcba'.

Si vous êtes arrivés jusque là, vous avez fait le tour d’à peu près tout ce qui est nécessaire pour couvrir les besoins du programmeur/algorithmicien généraliste au quotidien.

Bravo !

Sujet de TP

Le sujet de TP à proprement parler est en fait beaucoup plus court que l’introduction, puisqu’il suppose une certaine autonomie.

Chiffre de César

Écrivez une fonction :

   1 def cesar(message,cle):
   2         ...
   3         return code

qui renvoie le code du message, suivant le chiffre de César paramétré par l’entier cle. Pour mémoire, cela signifie que chaque lettre du message est remplacée par la lettre qui se trouve cle « cases » plus loin dans l’alphabet, quitte à revenir au début si on a atteint la fin de l’alphabet.

On pourra d’abord se contenter de transformer les lettres de l’alphabet latin, et on laissera les autres caractères inchangés.

Deux outils cruciaux :

  • la fonction ord, qui renvoie le numéro d’un caractère (et on admet que les lettres ont des codes consécutifs) ;

  • la fonction chr, inverse de la précédente.

N’hésitez bien sûr pas à définir des fonctions auxiliaires pour décomposer le travail. Elles pourront aussi être utiles pour la suite.

Faut-il écrire une autre fonction pour le décodage ?

Chiffre de Vigenère

Le chiffre de Vigenère généralise celui de César : la clé est maintenant un mot. Dans cette clé :

  • la lettre A représente un décalage de 0,

  • la lettre B représente un décalage de 1,

  • la lettre C représente un décalage de 2,

L’idée du code est la suivante :

  • on décale la première lettre du message d’après la première lettre de la clé ;
  • on décale la deuxième lettre du message d’après la deuxième lettre de la clé ;
  • quand on a épuisé la clé, on revient à sa première lettre…

Écrivez des fonctions :

   1 def vigenere(message,cle):
   2         ...
   3         return code

et

   1 def devigenere(code,cle):
   2         ...
   3         return message

qui réalisent le codage et le décodage.

Pour aller plus loin

Le sujet du TP de rentrée du niveau 2 propose une méthode de cryptanalyse du chiffre de Vigenère, basée sur la détection de motifs répétés et le calcul de l’indice de coïncidence. Le sujet est disponible en ligne sur http://isn.irem.univ-mrs.fr/formation/.

WikISN: InitiationPython3 (dernière édition le 2016-01-27 09:38:48 par LionelVaux)