IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Apprendre à programmer avec Python


précédentsommairesuivant

Chapitre 19 : Annexes

19-1. Installation de Python

Si vous souhaitez essayer Python sur votre ordinateur personnel, n'hésitez pas : l'installation est très facile (et parfaitement réversible).

19-2. Sous Windows

Sur le site web officiel de Python : http://www.python.org , vous trouverez dans la section « Download » des logiciels d'installation automatique pour les différentes versions de Python. Vous pouvez en confiance choisir la dernière version « de production ».

Par exemple, au 30/9/03, il s'agit de la version 2.3.1 - Fichier à télécharger : Python-2.3.1.exe

Copiez ce fichier dans un répertoire temporaire de votre machine, et exécutez-le. Python s'installera par défaut dans un répertoire nommé « Python** » (** indiquant les deux premiers chiffres du n° de version), et des icônes de lancement seront mises en place automatiquement.

Lorsque l'installation est terminée, vous pouvez effacer le contenu du répertoire temporaire.

19-3. Sous Linux

Vous avez probablement installé votre système Linux à l'aide d'une distribution commerciale telle que SuSE, RedHat ou Mandrake. Installez simplement les paquetages Python qui en font partie, en n'omettant pas Tkinter (parfois installé en même temps que la Python imaging library).

19-4. Sous MacOS

Vous trouverez différentes versions de Python pour MacOS 9 et Mac OS X sur le site web de Jack Jansen : http://homepages.cwi.nl/~jack/macpython


Remarque importante concernant les versions récentes de Python

Depuis l'apparition de la version 2.3, il est vivement recommandé aux francophones que nous sommes d'inclure l'un des pseudo-commentaires suivant au début de tous nos scripts Python (à la 1e ou 2e ligne) :

 
Sélectionnez
# -*- coding:Latin-1 -*-

Ou bien :

 
Sélectionnez
# -*- coding:Utf-8 -*-

Vous trouverez l'explication de cette nécessité à la page 40.

19-5. Installation de SciTE (Scintilla Text Editor)

SciTE est un excellent logiciel éditeur, capable d'effectuer la coloration syntaxique, l'autocomplétion et surtout le repliement de code (code folding), c'est à dire le masquage à volonté de différents blocs d'instructions (contenu d'une classe, d'une fonction, d'une boucle, etc.) : cette fonctionnalité se révèle extrêmement pratique lorsque vos scripts commencent à s'allonger ... Il intègre également une fenêtre de terminal ainsi qu'un raccourci pour lancement des scripts. Cet éditeur est disponible pour Windows et pour Linux.

Veuillez consulter le site web : http://www.scintilla.org/SciTE.html

19-5-1. Installation sous Linux :

L'éditeur Scintilla fait dorénavant partie des paquetages fournis d'office avec les distributions récentes de Linux. Sinon, téléchargez-le au départ du site web mentionné ci-dessus. Ensuite :

  • Télécharger l'archive gscite***.tgz puis l'extraire avec tar.
  • Installer l'exécutable SciTE dans /usr/local/bin
  • Installer tout le reste (fichiers *.properties) dans /usr/share/scite (et non /usr/share/gscite !)

19-5-2. Installation sous Windows :

  • Télécharger l'archive wscite***.zip puis l'extraire dans \Program files
  • Installer une icône de lancement pour l'exécutable SciTe.exe

19-5-3. Pour les deux versions :

On peut personnaliser beaucoup de choses (polices, etc.) en editant le fichier des proprietes globales (Menu Options → Open global options file)

Par exemple, pour activer de jolis symboles pour replier/deplier, dans la marge de gauche :

 
Sélectionnez
fold.symbols = 2           # pour de belles icônes + et - cerclées
fold.on.open = 1           # ainsi tout est plié au départ
margin.width =0            # pour supprimer la marge inutile

Pour forcer le remplacement automatique des tabulations par des groupes de 4 espaces :

 
Sélectionnez
tabsize = 4
indent.size = 4
use.tabs = 0

19-6. Installation des Python méga-widgets

Visitez le site web : http://pmw.sourceforge.net

et cliquez sur le lien : Download Pmw12tar.gz pour télécharger le fichier correspondant.

Décomprimez ce fichier archive dans un répertoire temporaire, à l'aide d'un logiciel de décompression tel que tar, Winzip, Info-Zip, unzip ....

Recopiez l'intégralité du sous-répertoire Pmw qui s'est créé automatiquement, dans le répertoire où se trouve déjà l'essentiel de votre installation de Python.

Sous Windows, il s'agira par exemple de C:\Python23

Sous Linux, il s'agira vraisemblablement de /usr/lib/python

19-7. Installation de Gadfly (système de bases de données)

Depuis le site http://sourceforge.net/projects/gadfly, télécharger le paquetage gadfly-1.0.0.tar.gz Il s'agit d'un fichier archive comprimé. Copiez ce fichier dans un répertoire temporaire.

19-7-1. Sous Windows :

Dans un répertoire temporaire quelconque, décomprimez le fichier archive à l'aide d'un logiciel tel que Winzip.

Ouvrez une fenêtre DOS et entrez dans le sous-répertoire qui s'est créé automatiquement.

Lancez la commande : python setup.py install C'est tout.

Vous pouvez éventuellement améliorer les performances, en ajoutant l'opération suivante :

Dans le sous-répertoire qui s'est créé, ouvrez le sous-répertoire kjbuckets, puis le sous-répertoire qui correspond à votre version de Python. Recopiez le fichier *.pyd qui s'y trouve dans le répertoire racine de votre installation de Python.

Lorsque tout est terminé, effacez le contenu de votre répertoire temporaire.

19-7-2. Sous Linux :

En tant qu'administrateur (root), choisissez un répertoire temporaire quelconque et décomprimez-y le fichier archive à l'aide de l'utilitaire tar, qui fait certainement partie de votre distribution. Entrez simplement la commande : tar -xvzf gadfly-1.0.0.tar.gz

Entrez dans le sous-répertoire qui s'est créé automatiquement : cd gadfly-1.0.0

Lancez la commande : python setup.py install C'est tout.

Si votre système Linux comporte un compilateur C, vous pouvez améliorer les performances de Gadfly en recompilant la bibliothèque kjbuckets. Pour ce faire, entrez encore les deux commandes suivantes :

cd kjbuckets

python setup.py install

Lorsque tout est terminé, effacez tout le contenu du répertoire temporaire.

19-9. Solutions aux exercices

Pour quelques exercices, nous ne fournissons pas de solution. Efforcez-vous de les trouver sans aide, même si cela vous semble difficile. C'est en effet en vous acharnant sur de tels problèmes que vous apprendrez le mieux.

Exercice 4.2 :

 
Sélectionnez
>>> c = 0
>>> while c < 20:
...     c = c +1
...     print c, "x 7 =", c*7

ou encore :

 
Sélectionnez
>>> c = 1
>>> while c <= 20:
...     print c, "x 7 =", c*7
...     c = c +1

Exercice 4.3 :

 
Sélectionnez
>>> s = 1
>>> while s <= 16384:
...     print s, "euro(s) =", s *1.65, "dollar(s)"
...     s = s *2

Exercice 4.4 :

 
Sélectionnez
>>> a, c = 1, 1
>>> while c < 13:
...     print a,
...     a, c = a *3, c+1

Exercice 4.6 :

 
Sélectionnez
# 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."

Exercice 4.7 :

 
Sélectionnez
# 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

Exercice 5.1 :

 
Sélectionnez
# 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)"

Exercice 5.3 :

 
Sélectionnez
# 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"

Exercice 5.5 :

 
Sélectionnez
>>> a, b = 1, 1				# variante :  a, b = 1., 1
>>> while b<65:
...     print b, a
...     a,b = a*2, b+1
...

Exercice 5.6 :

 
Sélectionnez
# Recherche d'un caractère particulier dans une chaîne
 
# Chaîne fournie au départ :
ch = "Monty python flying circus"
# Caractère à rechercher :
cr = "e"
# Recherche proprement dite :
lc = len(ch)    # nombre de caractères à tester
i = 0           # indice du caractère en cours d'examen
t = 0           # "drapeau" à lever si le caractère recherché est présent 
while i < lc:
    if ch[i] == cr:
        t = 1
    i = i + 1    
# Affichage :
print "Le caractère", cr,        
if t == 1:
    print "est présent",
else:
    print "est inrouvable",
print "dans la chaîne", ch

Exercice 5.8 :

 
Sélectionnez
# 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 car.)
while i < lc:
    nch = nch + cr + ch[i]
    i = i + 1    
# Affichage :
print nch

Exercice 5.9 :

 
Sélectionnez
# 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

Exercice 5.11 :

 
Sélectionnez
# 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

Exercice 5.12 :

 
Sélectionnez
# 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

Exercice 5.13 :

 
Sélectionnez
# 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

Exercice 5.14 :

 
Sélectionnez
# 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

Exercice 6.1 :

 
Sélectionnez
# Conversion de miles/heure en km/h et m/s
 
print "Veuillez entrer le nombre de miles parcourus en une heure : ",
ch = raw_input()            # en général préférable à input()
mph = float(ch)             # conversion de la chaîne entrée en nombre réel
mps = mph * 1609 / 3600     # conversion en mètres par seconde
kmph = mph * 1.609          # conversion en km/h
# affichage :
print mph, "miles/heure =", kmph, "km/h, ou encore", mps, "m/s"

Exercice 6.2 :

 
Sélectionnez
# Périmètre et Aire d'un triangle quelconque
 
from math import sqrt
 
print "Veuillez entrer le côté a : "
a = float(raw_input())
print "Veuillez entrer le côté b : "
b = float(raw_input())
print "Veuillez entrer le côté c : "
c = float(raw_input())
d = (a + b + c)/2                # demi-périmètre
s = sqrt(d*(d-a)*(d-b)*(d-c))    # aire (suivant formule)
 
print "Longueur des côtés =", a, b, c
print "Périmètre =", d*2, "Aire =", s

Exercice 6.4 :

 
Sélectionnez
# Entrée d'éléments dans une liste
 
tt = []             # Liste à compléter (vide au départ)
ch = "start"        # valeur quelconque (mais non nulle) 
while ch != "":
    print "Veuillez entrer une valeur : "
    ch = raw_input()
    if ch != "":
        tt.append(float(ch))        # variante : tt.append(ch)    
 
# affichage de la liste :
print tt

Exercice 6.8 :

 
Sélectionnez
# Traitement de nombres entiers compris entre deux limites
 
print "Veuillez entrer la limite inférieure :",
a = input()
print "Veuillez entrer la limite supérieure :",
b = input()
s = 0                   # somme recherchée (nulle au départ)
# Parcours de la série des nombres compris entre a et b :
n = a                   # nombre en cours de traitement
while n <= b:
    if n % 3 ==0 and n % 5 ==0:      # variante : 'or' au lieu de 'and'
        s = s + n
    n = n + 1
 
print "La somme recherchée vaut", s

Exercice 6.9 :

 
Sélectionnez
# Années bissextiles
 
print "Veuillez entrer l'année à tester :",
a = input()
 
if a % 4 != 0:
    # a n'est pas divisible par 4 -> année non bissextile
    bs = 0      
else:
    if a % 400 ==0:
        # a divisible par 400 -> année bissextile
        bs = 1
    elif a % 100 ==0:
        # a divisible par 100 -> année non bissextile
        bs = 0
    else:
        # autres cas ou a est divisible par 4 -> année bissextile
        bs = 1
if bs ==1:
    ch = "est"
else:
    ch = "n'est pas"
print "L'année", a, ch, "bissextile."
 
Variante (proposée par Alex Misbah ) :
a=input('entrée une année:')
 
if (a%4==0) and ((a0!=0) or (a@0==0)):
    print a,"est une année bissextile"
else:
    print a,"n'est pas une année bissextile"

Exercice 6.11 : Calculs de triangles

 
Sélectionnez
from sys import exit      # module contenant des fonctions système
 
print """
Veuillez entrer les longueurs des 3 côtés
(en séparant ces valeurs à l'aide de virgules) :"""
a, b, c = input()
# Il n'est possible de construire un triangle que si chaque côté
# a une longueur inférieure à la somme des deux autres :
if a < (b+c) and b < (a+c) and c < (a+b) :
    print "Ces trois longueurs déterminent bien un triangle."
else:
    print "Il est impossible de construire un tel triangle !"
    exit()          # ainsi l'on n'ira pas plus loin. 
 
f = 0
if a == b and b == c :
    print "Ce triangle est équilatéral."
    f = 1
elif a == b or b == c or c == a :
    print "Ce triangle est isocèle."
    f = 1
if a*a + b*b == c*c or b*b + c*c == a*a or c*c + a*a == b*b :
    print "Ce triangle est rectangle."
    f = 1
if f == 0 :
    print "Ce triangle est quelconque."

Exercice 6.15 :

 
Sélectionnez
# Notes de travaux scolaires
 
notes = []           # liste à construire  
n = 2                # valeur positive quelconque pour initier la boucle
while n >= 0 :
    print "Entrez la note suivante, s.v.p. : ",
    n = float(raw_input())      # conversion de l'entrée en un nombre réel
    if n < 0 :
        print "OK. Terminé."
    else:    
        notes.append(n)         # ajout d'une note à la liste
        # Calculs divers sur les notes déjà entrées :
        # valeurs minimale et maximale + total de toutes les notes. 
        min = 500               # valeur supérieure à toute note
        max, tot, i = 0, 0, 0        
        nn = len(notes)         # nombre de notes déjà entrées
        while i < nn:
            if notes[i] > max:
                max = notes[i]
            if notes[i] < min:
                min = notes[i]
            tot = tot + notes[i]
            moy = tot/nn
            i = i + 1
        print nn, "notes entrées. Max =", max, "Min =", min, "Moy =", moy

Exercice 7.3 :

 
Sélectionnez
from math import pi
 
def surfCercle(r):
    "Surface d'un cercle de rayon r"
    return pi * r**2
 
# test :
print surfCercle(2.5)

Exercice 7.4 :

 
Sélectionnez
def volBoite(x1, x2, x3):
    "Volume d'une boîte parallélipipédique"
    return x1 * x2 * x3
 
# test :
print volBoite(5.2, 7.7, 3.3)

Exercice 7.5 :

 
Sélectionnez
def maximum(n1, n2, n3):
    "Renvoie le plus grand de trois nombres"
    if n1 >= n2 and n1 >= n3:
        return n1
    elif n2 >= n1 and n2 >= n3:
        return n2
    else:
        return n3
 
# test :
print maximum(4.5, 5.7, 3.9)

Exercice 7.9 :

 
Sélectionnez
def compteCar(ca, ch):
    "Renvoie le nombre de caractères ca trouvés dans la chaîne ch"
    i, tot = 0, 0
    while i < len(ch):
        if ch[i] == ca:
            tot = tot + 1
        i = i + 1
    return tot    
 
# test :
print compteCar("e","Cette chaîne est un exemple")

Exercice 7.10 :

 
Sélectionnez
def indexMax(tt):
    "renvoie l'indice du plus grand élément de la liste tt"
    i, max = 0, 0
    while i < len(tt):
        if tt[i] > max :
            max, imax = tt[i], i
        i = i + 1    
    return imax
 
# test :
serie = [5, 8, 2, 1, 9, 3, 6, 4]
print indexMax(serie)

Exercice 7.11 :

 
Sélectionnez
def nomMois(n):
    "renvoie le nom du n-ième mois de l'année"
    mois = ['Janvier,', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet',
            'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
    return mois[n -1]       # les indices sont numérotés à partir de zéro
 
# test :
print nomMois(4)

Exercice 7.14 :

 
Sélectionnez
def volBoite(x1 =10, x2 =10, x3 =10):
    "Volume d'une boîte parallélipipédique"
    return x1 * x2 * x3
 
# test :
print volBoite()
print volBoite(5.2)
print volBoite(5.2, 3)

Exercice 7.15 :

 
Sélectionnez
def volBoite(x1 =-1, x2 =-1, x3 =-1):
    "Volume d'une boîte parallélipipédique"
    if x1 == -1 :
        return x1           # aucun argument n'a été fourni
    elif x2 == -1 :
        return x1**3        # un seul argument -> boîte cubique
    elif x3 == -1 :
        return x1*x1*x2     # deux arguments -> boîte prismatique
    else :
        return x1*x2*x3
 
# test :
print volBoite()
print volBoite(5.2)
print volBoite(5.2, 3)
print volBoite(5.2, 3, 7.4)

Exercice 7.16 :

 
Sélectionnez
def changeCar(ch, ca1, ca2, debut =0, fin =-1):
    "Remplace tous les caractères ca1 par des ca2 dans la chaîne ch"
    if fin == -1:
        fin = len(ch)
    nch, i = "", 0            # nch : nouvelle chaîne à construire
    while i < len(ch) :
        if i >= debut and i <= fin and ch[i] == ca1:
            nch = nch + ca2
        else :
            nch = nch + ch[i]
        i = i + 1
    return nch
 
# test :
print changeCar("Ceci est une toute petite phrase", " ", "*")
print changeCar("Ceci est une toute petite phrase", " ", "*", 8, 12)
print changeCar("Ceci est une toute petite phrase", " ", "*", 12)

Exercice 7.17 :

 
Sélectionnez
def eleMax(lst, debut =0, fin =-1):
    "renvoie le plus grand élément de la liste lst"
    if fin == -1:
        fin = len(lst)
    max, i = 0, 0
    while i < len(lst):
        if i >= debut and i <= fin and lst[i] > max:
            max = lst[i]
        i = i + 1
    return max
 
# test :
serie = [9, 3, 6, 1, 7, 5, 4, 8, 2]
print eleMax(serie)
print eleMax(serie, 2)
print eleMax(serie, 2, 5)

Exercice 8.7 :

 
Sélectionnez
from Tkinter import *
 
# Coordonnées X,Y des 5 anneaux :
coord = [[20,30], [120,30], [220, 30], [70,80], [170,80]]
# Couleurs des 5 anneaux :
coul = ["red", "yellow", "blue", "green", "black"]
 
base = Tk()
can = Canvas(base, width =335, height =200, bg ="white")
can.pack()
bou = Button(base, text ="Quitter", command =base.quit)
bou.pack(side = RIGHT)
# Dessin des 5 anneaux :
i = 0
while i < 5:
    x1, y1 = coord[i][0], coord[i][1]
    can.create_oval(x1, y1, x1+100, y1 +100, width =2, outline =coul[i])
    i = i +1
base.mainloop()

Variante :

 
Sélectionnez
from Tkinter import *
 
# Dessin des 5 anneaux :
def dessineCercle(i):
    x1, y1 = coord[i][0], coord[i][1]
    can.create_oval(x1, y1, x1+100, y1 +100, width =2, outline =coul[i])
 
def a1():
    dessineCercle(0)
 
def a2():
    dessineCercle(1)
 
def a3():
    dessineCercle(2)
 
def a4():
    dessineCercle(3)
 
def a5():
    dessineCercle(4)
 
# Coordonnées X,Y des 5 anneaux :
coord = [[20,30], [120,30], [220, 30], [70,80], [170,80]]
# Couleurs des 5 anneaux :
coul = ["red", "yellow", "blue", "green", "black"]
 
base = Tk()
can = Canvas(base, width =335, height =200, bg ="white")
can.pack()
bou = Button(base, text ="Quitter", command =base.quit)
bou.pack(side = RIGHT)
 
# Installation des 5 boutons :    
Button(base, text='1', command = a1).pack(side =LEFT)    
Button(base, text='2', command = a2).pack(side =LEFT)    
Button(base, text='3', command = a3).pack(side =LEFT)    
Button(base, text='4', command = a4).pack(side =LEFT)    
Button(base, text='5', command = a5).pack(side =LEFT)    
base.mainloop()
Image non disponible

Exercices 8.9 et 8.10 :

 
Sélectionnez
# Dessin d'un damier, avec placement de pions au hasard
 
from Tkinter import *
from random import randrange        # générateur de nombres aléatoires
 
def damier():
    "dessiner dix lignes de carrés avec décalage alterné"
    y = 0
    while y < 10:
        if y % 2 == 0:              # une fois sur deux, on
            x = 0                   # commencera la ligne de
        else:                       # carrés avec un décalage
            x = 1                   # de la taille d'un carré
        ligne_de_carres(x*c, y*c)
        y += 1
 
def ligne_de_carres(x, y):
    "dessiner une ligne de carrés, en partant de x, y" 
    i = 0
    while i < 10:
        can.create_rectangle(x, y, x+c, y+c, fill='navy')
        i += 1
        x += c*2                    # espacer les carrés
 
def cercle(x, y, r, coul):
    "dessiner un cercle de centre x,y et de rayon r"
    can.create_oval(x-r, y-r, x+r, y+r, fill=coul)
 
def ajouter_pion():
    "dessiner un pion au hasard sur le damier"
    # tirer au hasard les coordonnées du pion :
    x = c/2 + randrange(10) * c
    y = c/2 + randrange(10) * c
    cercle(x, y, c/3, 'red')
 
##### Programme principal : ############
 
# Tâchez de bien "paramétrer" vos programmes, comme nous l'avons
# fait dans ce script. Celui-ci peut en effet tracer des damiers
# de n'importe quelle taille en changeant seulement la valeur
# d'une seule variable, à savoir la dimension des carrés : 
 
c = 30                  # taille des carrés
 
fen = Tk()
can = Canvas(fen, width =c*10, height =c*10, bg ='ivory')
can.pack(side =TOP, padx =5, pady =5)
b1 = Button(fen, text ='damier', command =damier)
b1.pack(side =LEFT, padx =3, pady =3)
b2 = Button(fen, text ='pions', command =ajouter_pion)
b2.pack(side =RIGHT, padx =3, pady =3)
fen.mainloop()#

Exercice 8.12 :

 
Sélectionnez
# Simulation du phénomène de gravitation universelle
 
from Tkinter import *
from math import sqrt
 
def distance(x1, y1, x2, y2):
    "distance séparant les points x1,y1 et x2,y2"
    d = sqrt((x2-x1)**2 + (y2-y1)**2)       # théorème de Pythagore
    return  d
 
def forceG(m1, m2, di):
    "force de gravitation s'exerçant entre m1 et m2 pour une distance di"
    return m1*m2*6.67e-11/di**2             # loi de Newton
 
def avance(n, gd, hb):
    "déplacement de l'astre n, de gauche à droite ou de haut en bas"
    global x, y, step
    # nouvelles coordonnées :
    x[n], y[n] = x[n] +gd, y[n] +hb
    # déplacement du dessin dans le canevas :
    can.coords(astre[n], x[n]-10, y[n]-10, x[n]+10, y[n]+10)
    # calcul de la nouvelle interdistance : 
    di = distance(x[0], y[0], x[1], y[1])
    # conversion de la distance "écran" en distance "astronomique" :
    diA = di*1e9            # (1 pixel => 1 million de km) 
    # calcul de la force de gravitation correspondante :
    f = forceG(m1, m2, diA)
    # affichage des nouvelles valeurs de distance et force : 
    valDis.configure(text="Distance = " +str(diA) +" m")
    valFor.configure(text="Force = " +str(f) +" N")
    # adaptation du "pas" de déplacement en fonction de la distance :
    step = di/10
 
def gauche1():
    avance(0, -step, 0)
 
def droite1():
    avance(0, step, 0)
 
def haut1():
    avance(0, 0, -step)
 
def bas1():
    avance(0, 0, step)
 
def gauche2():
    avance(1, -step, 0)
 
def droite2():
    avance (1, step, 0)
 
def haut2():
    avance(1, 0, -step)
 
def bas2():
    avance(1, 0, step)
 
# Masses des deux astres :
m1 = 6e24          # (valeur de la masse de la terre, en kg)
m2 = 6e24          # 
astre = [0]*2      # liste servant à mémoriser les références des dessins
x =[50., 350.]     # liste des coord. X de chaque astre (à l'écran)
y =[100., 100.]    # liste des coord. Y de chaque astre
step =10           # "pas" de déplacement initial
 
# Construction de la fenêtre :
fen = Tk()
fen.title(' Gravitation universelle suivant Newton')
# Libellés :
valM1 = Label(fen, text="M1 = " +str(m1) +" kg")
valM1.grid(row =1, column =0)
valM2 = Label(fen, text="M2 = " +str(m2) +" kg")
valM2.grid(row =1, column =1)
valDis = Label(fen, text="Distance")
valDis.grid(row =3, column =0)
valFor = Label(fen, text="Force")
valFor.grid(row =3, column =1)
# Canevas avec le dessin des 2 astres:
can = Canvas(fen, bg ="light yellow", width =400, height =200)
can.grid(row =2, column =0, columnspan =2)
astre[0] = can.create_oval(x[0]-10, y[0]-10, x[0]+10, y[0]+10,
                           fill ="red", width =1)
astre[1] = can.create_oval(x[1]-10, y[1]-10, x[1]+10, y[1]+10,
                           fill ="blue", width =1)
# 2 groupes de 4 boutons, chacun installé dans un cadre (frame) :
fra1 = Frame(fen)
fra1.grid(row =4, column =0, sticky =W, padx =10)
Button(fra1, text="<-", fg ='red',command =gauche1).pack(side =LEFT)
Button(fra1, text="->", fg ='red', command =droite1).pack(side =LEFT)
Button(fra1, text="^", fg ='red', command =haut1).pack(side =LEFT)
Button(fra1, text="v", fg ='red', command =bas1).pack(side =LEFT)
fra2 = Frame(fen)
fra2.grid(row =4, column =1, sticky =E, padx =10)
Button(fra2, text="<-", fg ='blue', command =gauche2).pack(side =LEFT)
Button(fra2, text="->", fg ='blue', command =droite2).pack(side =LEFT)
Button(fra2, text="^", fg ='blue', command =haut2).pack(side =LEFT)
Button(fra2, text="v", fg ='blue', command =bas2).pack(side =LEFT)
 
fen.mainloop()
Image non disponible

Exercice 8.16 :

 
Sélectionnez
# Conversions de températures Fahrenheit <=> Celsius
 
from Tkinter import *
 
def convFar(event):
    "valeur de cette température, exprimée en degrés Fahrenheit" 
    tF = eval(champTC.get())
    varTF.set(str(tF*1.8 +32))
 
def convCel(event):
    "valeur de cette température, exprimée en degrés Celsius" 
    tC = eval(champTF.get())
    varTC.set(str((tC-32)/1.8))
 
fen = Tk()
fen.title('Fahrenheit/Celsius')
 
Label(fen, text='Temp. Celsius :').grid(row =0, column =0)
# "variable Tkinter" associée au champ d'entrée. Cet "objet-variable"
# assure l'interface entre TCL et Python (voir notes, page 165) :
varTC =StringVar()          
champTC = Entry(fen, textvariable =varTC)
champTC.bind("<Return>", convFar)
champTC.grid(row =0, column =1)
# Initialisation du contenu de la variable Tkinter :
varTC.set("100.0")
 
Label(fen, text='Temp. Fahrenheit :').grid(row =1, column =0) 
varTF =StringVar()
champTF = Entry(fen, textvariable =varTF)
champTF.bind("<Return>", convCel)
champTF.grid(row =1, column =1)
varTF.set("212.0")
 
fen.mainloop()
Image non disponible

Exercice 8.18 à 8.20 :

 
Sélectionnez
# Cercles et courbes de Lissajous
 
from Tkinter import *
from math import sin, cos
 
def move():    
    global ang, x, y
    # on mémorise les coord. précédentes avant de calculer les nouvelles :
    xp, yp = x, y
    # rotation d'un angle de 0.1 radian :
    ang = ang +.1 
    # sinus et cosinus de cet angle => coord. d'un point du cercle trigono.
    x, y = sin(ang), cos(ang)
    # Variante déterminant une courbe de Lissajous avec f1/f2 = 2/3 :
    # x, y = sin(2*ang), cos(3*ang)
    # mise à l'échelle (120 = rayon du cercle, (150,150) = centre du canevas)
    x, y = x*120 + 150, y*120 + 150
    can.coords(balle, x-10, y-10, x+10, y+10)
    can.create_line(xp, yp, x, y, fill ="blue")
 
ang, x, y = 0., 150., 270.
fen = Tk()
fen.title('Courbes de Lissajous')
can = Canvas(fen, width =300, height=300, bg="white")
can.pack()
balle = can.create_oval(x-10, y-10, x+10, y+10, fill='red')
Button(fen, text='Go', command =move).pack()
 
fen.mainloop()
Image non disponible

Exercice 8.27 :

 
Sélectionnez
# Chutes et rebonds
 
from Tkinter import *
 
def move():
    global x, y, v, dx, dv, flag
    xp, yp = x, y            # mémorisation des coord. précédentes
    # déplacement horizontal :
    if x > 385 or x < 15 :   # rebond sur les parois latérales :
        dx = -dx             # on inverse le déplacement
    x = x + dx
    # variation de la vitesse verticale (toujours vers le bas):
    v = v + dv
    # déplacement vertical (proportionnel à la vitesse)
    y = y + v       
    if y > 240:              # niveau du sol à 240 pixels : 
        y = 240              #  défense d'aller + loin !
        v = -v               # rebond : la vitesse s'inverse
    # on repositionne la balle :    
    can.coords(balle, x-10, y-10, x+10, y+10)
    # on trace un bout de trajectoire :
    can.create_line(xp, yp, x, y, fill ='light grey')
    # ... et on remet ça jusqu'à plus soif :
    if flag > 0:
        fen.after(50,move)
 
def start():
    global flag
    flag = flag +1
    if flag == 1:
        move()
 
def stop():
    global flag
    flag =0
 
# initialisation des coordonnées, des vitesses et du témoin d'animation :    
x, y, v, dx, dv, flag  = 15, 15, 0, 6, 5, 0
 
fen = Tk()
fen.title(' Chutes et rebonds')
can = Canvas(fen, width =400, height=250, bg="white")
can.pack()
balle = can.create_oval(x-10, y-10, x+10, y+10, fill='red')
Button(fen, text='Start', command =start).pack(side =LEFT, padx =10)
Button(fen, text='Stop', command =stop).pack(side =LEFT)
Button(fen, text='Quitter', command =fen.quit).pack(side =RIGHT, padx =10)
 
fen.mainloop()
Image non disponible

Exercice 9.1 (éditeur simple, pour lire et écrire dans un fichier 'texte') :

 
Sélectionnez
def sansDC(ch):
    "cette fonction renvoie la chaîne ch amputée de son dernier caractère"
    nouv = ""
    i, j = 0, len(ch) -1        
    while i < j:
        nouv = nouv + ch[i]
        i = i + 1
    return nouv    
 
def ecrireDansFichier():
    of = open(nomF, 'a')
    while 1:
        ligne = raw_input("entrez une ligne de texte (ou <Enter>) : ")
        if ligne == '':
            break
        else:
            of.write(ligne + '\n')
    of.close()
 
def lireDansFichier():
    of = open(nomF, 'r')
    while 1:
        ligne = of.readline()
        if ligne == "":
            break
        # afficher en omettant le dernier caractère (= fin de ligne) :
        print sansDC(ligne)
    of.close()        
 
nomF = raw_input('Nom du fichier à traiter : ')
choix = raw_input('Entrez "e" pour écrire, "c" pour consulter les données : ')
 
if choix =='e':    
    ecrireDansFichier()
else:
    lireDansFichier()

Exercice 9.3 (génération des tables de multiplication de 2 à 30) :

 
Sélectionnez
def tableMulti(n):
    # Fonction générant la table de multiplication par n (20 termes)
    # La table sera renvoyée sous forme d'une chaîne de caractères :
    i, ch = 0, ""
    while i < 20:        
        i = i + 1
        ch = ch + str(i * n) + " "
    return ch
 
NomF = raw_input("Nom du fichier à créer : ")
fichier = open(NomF, 'w')
 
# Génération des tables de 2 à 30 :
table = 2
while table < 31:
    fichier.write(tableMulti(table) + '\n')
    table = table + 1
fichier.close()
Exercice 9.4 :
# Triplement des espaces dans un fichier texte.
# Ce script montre également comment modifier le contenu d'un fichier
# en le transférant d'abord tout entier dans une liste, puis en
# réenregistrant celle-ci après modifications
 
def triplerEspaces(ch):
    "fonction qui triple les espaces entre mots dans la chaîne ch"
    i, nouv = 0, ""
    while i < len(ch):
        if ch[i] == " ":
            nouv = nouv + "   "
        else:
            nouv = nouv + ch[i]
        i = i +1    
    return nouv
 
NomF = raw_input("Nom du fichier : ")
fichier = open(NomF, 'r+')              # 'r+' = mode read/write
lignes = fichier.readlines()            # lire toutes les lignes
 
n=0
while n < len(lignes):
    lignes[n] = triplerEspaces(lignes[n])
    n =n+1
 
fichier.seek(0)                         # retour au début du fichier
fichier.writelines(lignes)              # réenregistrement
fichier.close()

Exercice 9.5 :

 
Sélectionnez
# Mise en forme de données numériques.
# Le fichier traité est un fichier texte dont chaque ligne contient un nombre
# réel (sans exposants et encodé sous la forme d'une chaîne de caractères)    
 
def valArrondie(ch):
    "représentation arrondie du nombre présenté dans la chaîne ch"
    f = float(ch)       # conversion de la chaîne en un nombre réel
    e = int(f + .5)     # conversion en entier (On ajoute d'abord
                        # 0.5 au réel pour l'arrondir correctement)
    return str(e)       # reconversion en chaîne de caractères
 
fiSource = raw_input("Nom du fichier à traiter : ")
fiDest = raw_input("Nom du fichier destinataire : ")
fs = open(fiSource, 'r')
fd = open(fiDest, 'w')
 
while 1:
    ligne = fs.readline()       # lecture d'une ligne du fichier
    if ligne == "" or ligne == "\n":
        break
    ligne = valArrondie(ligne)
    fd.write(ligne +"\n")
 
fd.close()
fs.close()
Exercice 9.6 :
# Comparaison de deux fichiers, caractère par caractère :
 
fich1 = raw_input("Nom du premier fichier : ")
fich2 = raw_input("Nom du second fichier : ")
fi1 = open(fich1, 'r')
fi2 = open(fich2, 'r')
 
c, f = 0, 0                 # compteur de caractères et "drapeau" 
while 1:
    c = c + 1
    car1 = fi1.read(1)      # lecture d'un caractère dans chacun
    car2 = fi2.read(1)      # des deux fichiers
    if car1 =="" or car2 =="":
        break
    if car1 != car2 :
        f = 1
        break               # différence trouvée
 
fi1.close()
fi2.close()
 
print "Ces 2 fichiers",
if f ==1:
    print "diffèrent à partir du caractère n°", c
else:
    print "sont identiques."

Exercice 9.7 :

 
Sélectionnez
# Combinaison de deux fichiers texte pour en faire un nouveau
 
fichA = raw_input("Nom du premier fichier : ")
fichB = raw_input("Nom du second fichier : ")
fichC = raw_input("Nom du fichier destinataire : ")
fiA = open(fichA, 'r')
fiB = open(fichB, 'r')
fiC = open(fichC, 'w')
 
while 1:
    ligneA = fiA.readline()    
    ligneB = fiB.readline()
    if ligneA =="" and ligneB =="":
        break               # On est arrivé à la fin des 2 fichiers
    if ligneA != "":
        fiC.write(ligneA)
    if ligneB != "":    
        fiC.write(ligneB)
 
fiA.close()
fiB.close()
fiC.close()
Exercice 9.8 :
# Enregistrer les coordonnées des membres d'un club
 
def encodage():
    "renvoie la liste des valeurs entrées, ou une liste vide"
    print "*** Veuillez entrer les données (ou <Enter> pour terminer) :"
    while 1:
        nom = raw_input("Nom : ")
        if nom == "":
            return []
        prenom = raw_input("Prénom : ")
        rueNum = raw_input("Adresse (N° et rue) : ")
        cPost = raw_input("Code postal : ")
        local = raw_input("Localité : ")
        tel = raw_input("N° de téléphone : ")
        print nom, prenom, rueNum, cPost, local, tel
        ver = raw_input("Entrez <Enter> si c'est correct, sinon <n> ")
        if ver == "":
            break
    return [nom, prenom, rueNum, cPost, local, tel]
 
def enregistrer(liste):
    "enregistre les données de la liste en les séparant par des <#>"
    i = 0
    while i < len(liste):
        of.write(liste[i] + "#")
        i = i + 1
    of.write("\n")              # caractère de fin de ligne    
 
nomF = raw_input('Nom du fichier destinataire : ')
of = open(nomF, 'a')
while 1:
    tt = encodage()
    if tt == []:
        break
    enregistrer(tt)
 
of.close()

Exercice 9.9 :

 
Sélectionnez
# Ajouter des informations dans le fichier du club
 
def traduire(ch):
    "convertir une ligne du fichier source en liste de données"
    dn = ""                 # chaîne temporaire pour extraire les données  
    tt = []                 # la liste à produire
    i = 0
    while i < len(ch):
        if ch[i] == "#":
            tt.append(dn)   # on ajoute la donnée à la liste, et   
            dn =""          # on réinitialise la chaine temporaire
        else:    
            dn = dn + ch[i]
        i = i + 1
    return tt    
 
def encodage(tt):
    "renvoyer la liste tt, complétée avec la date de naissance et le sexe"
    print "*** Veuillez entrer les données (ou <Enter> pour terminer) :"
    # Affichage des données déjà présentes dans la liste :
    i = 0
    while i < len(tt):
        print tt[i],
        i = i +1
    print
    while 1:
        daNai = raw_input("Date de naissance : ")
        sexe = raw_input("Sexe (m ou f) : ")
        print daNai, sexe
        ver = raw_input("Entrez <Enter> si c'est correct, sinon <n> ")
        if ver == "":
            break
    tt.append(daNai)
    tt.append(sexe)
    return tt
 
def enregistrer(tt):
    "enregistrer les données de la liste tt en les séparant par des <#>"
    i = 0
    while i < len(tt):
        fd.write(tt[i] + "#")
        i = i + 1
    fd.write("\n")          # caractère de fin de ligne
 
fSource = raw_input('Nom du fichier source : ')
fDest = raw_input('Nom du fichier destinataire : ')
fs = open(fSource, 'r')
fd = open(fDest, 'w')
while 1:
    ligne = fs.readline()           # lire une ligne du fichier source
    if ligne =="" or ligne =="\n":
        break
    liste = traduire(ligne)         # la convertir en une liste
    liste = encodage(liste)         # y ajouter les données supplémentaires
    enregistrer(liste)              # sauvegarder dans fichier dest.
 
fd.close()
fs.close()

Exercice 9.10 :

 
Sélectionnez
# Recherche de lignes particulières dans un fichier texte :
 
def chercheCP(ch):
    "recherche dans ch la portion de chaîne contenant le code postal"
    i, f, ns = 0, 0, 0          # ns est un compteur de codes #
    cc = ""                     # chaîne à construire 
    while i < len(ch):
        if ch[i] =="#":
            ns = ns +1
            if ns ==3:          # le CP se trouve après le 3e code #
                f = 1           # variable "drapeau" (flag)
            elif ns ==4:        # inutile de lire après le 4e code #
                break
        elif f ==1:             # le caractère lu fait partie du
            cc = cc + ch[i]     # CP recherché -> on mémorise
        i = i +1
    return cc    
 
nomF = raw_input("Nom du fichier à traiter : ")
codeP = raw_input("Code postal à rechercher : ")
fi = open(nomF, 'r')
while 1:
    ligne = fi.readline()
    if ligne =="":
        break
    if chercheCP(ligne) == codeP:
        print ligne
fi.close()

Exercice 10.2 (découpage d'une chaîne en fragments) :

 
Sélectionnez
def decoupe(ch, n):
    "découpage de la chaîne ch 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(ch):
        if f > len(ch):     # on ne peut pas découper au-delà de la fin
            f = len(ch)
        fr = ch[d:f]        # découpage d'un fragment
        tt.append(fr)       # ajout du fragment à la liste
        d, f = f, f +n      # indices suivants 
    return tt
 
def inverse(tt):
    "rassemble les éléments de la liste tt dans l'ordre inverse"
    ch = ""                 # 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
        ch = ch + tt[i]
    return ch
 
# Test :
ch ="abcdefghijklmnopqrstuvwxyz123456789"
liste = decoupe(ch, 5)
print liste
print inverse(liste)

Exercice 10.3 :

 
Sélectionnez
# Rechercher l'indice d'un caractère dans une chaîne
 
def trouve(ch, car, deb=0):
    "trouve l'indice du caractère car dans la chaîne ch"
    i = deb
    while i < len(ch):
        if ch[i] == car:
            return i		# le caractère est trouvé -> on termine
        i = i + 1
    return -1       		# toute la chaîne a été scannée sans succès 
 
# Tests :
print trouve("Coucou c'est moi", "z")
print trouve("Juliette & Roméo", "&")
print trouve("César & Cléopâtre", "r", 5)

Exercice 10.6 :

 
Sélectionnez
prefixes, suffixe = "JKLMNOP", "ack"
 
for p in prefixes:
    print p + suffixe

Exercice 10.7 :

 
Sélectionnez
def compteMots(ch):
    "comptage du nombre de mots dans la chaîne ch"
    if len(ch) ==0:
        return 0
    nm = 1                  # la chaîne comporte au moins un mot          
    for c in ch:
        if c == " ":        # il suffit de compter les espaces
            nm = nm + 1
    return nm
 
# Test :
print compteMots("Les petits ruisseaux font les grandes rivières")

Exercice 10.8 :

 
Sélectionnez
def majuscule(car):
    "renvoie <vrai> si car est une majuscule"
    if car in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
        return 1
    else:
        return 0

Exercice 10.10 :

 
Sélectionnez
def chaineListe(ch):
    "convertit la chaîne ch en une liste de mots"
    liste, ct = [], ""          # ct est une chaîne temporaire
    for c in ch:
        if c == " ":
            liste.append(ct)    # ajouter la ch. temporaire à la liste
            ct = ""             # ré-initialiser la ch. temporaire
        else:    
            ct = ct + c
    if ct != "":        
        liste.append(ct)        # ne pas oublier le dernier mot        
    return liste
 
# Test :
print chaineListe("Une hirondelle ne fait pas le printemps")
print chaineListe("")

Exercice 10.11 (utilise les deux fonctions définies dans les exercices précédents) :

 
Sélectionnez
txt = "Le nom de ce Monsieur est Alphonse"
lst = chaineListe(txt)          # convertir la phrase en une liste de mots
for mot in lst:                 # analyser chacun des mots de la liste
    if majuscule(mot[0]):       # tester le premier caractère du mot
        print mot

Exercice 10.12 :

 
Sélectionnez
def majuscule(car):
    "renvoie <vrai> si car est une majuscule"
    if car >= "A" and car <= "Z":
        return 1
    else:
        return 0
 
def minuscule(car):
    "renvoie <vrai> si car est une minuscule"
    if car >= "a" and car <= "z":
        return 1
    else:
        return 0
 
def alphab(car):
    "renvoie <vrai> si car est un caractère alphabétique"
    if majuscule(car) or minuscule(car):
        return 1
    else:
        return 0

Exercice 10.15 (utilise deux fonctions définies dans les exercices précédents) :

 
Sélectionnez
def compteMaj(ch):
    "comptage des mots débutant par une majuscule dans la chaîne ch"
    c = 0
    lst = chaineListe(ch)       # convertir la phrase en une liste de mots
    for mot in lst:             # analyser chacun des mots de la liste
        if majuscule(mot[0]):   # tester le premier caractère du mot
            c = c +1
    return c    
 
# Test :
print compteMaj("Les filles Tidgout se nomment Justine et Corinne")

Exercice 10.16 (table des codes ASCII) :

 
Sélectionnez
c = 32      # Premier code ASCII <imprimable>
 
while c < 128 :                 # caractères non accentués seulement 
    print "Code", c, ":", chr(c), "  ",
    c = c + 1

Exercice 10.18 (Convertir majuscules -> minuscules et inversément) :

 
Sélectionnez
def convMajMin(ch):
    "échange les majuscules et les minuscules dans la chaîne ch"
    nouvC = ""                   # chaîne à construire
    for car in ch:
        code = ord(car)
        if car >= "A" and car <= "Z":
            code = code + 32
        elif car >= "a" and car <= "z":
            code = code - 32
        nouvC = nouvC + chr(code)
    return nouvC
 
# Test :
print convMajMin("Ferdinand-Charles de CAMARET")

Exercice 10.20 (Comptage de voyelles) :

 
Sélectionnez
def voyelle(car):
    "teste si car est une voyelle"
    if car in "AEIOUYaeiouy":
        return 1
    else:
        return 0
 
def compteVoyelles(ch):
    "compte les voyelles présentes dans la chaîne ch"
    n = 0
    for c in ch:
        if voyelle(c):
            n = n + 1
    return n
 
# Test :
print compteVoyelles("Monty Python Flying Circus")

Exercice 10.22 :

 
Sélectionnez
# Comptage du nombre de mots dans un texte
 
fiSource = raw_input("Nom du fichier à traiter : ")
fs = open(fiSource, 'r')
 
n = 0           # variable compteur
while 1:
    ch = fs.readline()
    if ch == "":
        break
    # conversion de la chaîne lue en une liste de mots :
    li = ch.split()
    # totalisation des mots :
    n = n + len(li)    
fs.close()
print "Ce fichier texte contient un total de %s mots" % (n)

Exercice 10.23 :

 
Sélectionnez
# Conversion en majuscule du premier caractère de chaque ligne
 
fiSource = raw_input("Nom du fichier à traiter : ")
fiDest = raw_input("Nom du fichier destinataire : ")
fs = open(fiSource, 'r')
fd = open(fiDest, 'w')
 
while 1:
    ch = fs.readline()
    if ch == "":
        break
    if ch[0] >= "A" and ch[0] <= "Z":
        # le premier car. est une majuscule. On passe.
        pass
    else:
        # Reconstruction de la chaîne:
        pc = ch[0].upper()      # Premier caractère converti
        rc = ch[1:]             # toute le reste de la chaîne  
        ch = pc + rc            # fusion
        # variante utilisant une méthode encore plus intégrée :
        # ch = ch.capitalize()
    # Transcription :    
    fd.write(ch)
 
fd.close()    
fs.close()

Exercice 10.24 :

 
Sélectionnez
# Fusion de lignes pour former des phrases
 
fiSource = raw_input("Nom du fichier à traiter : ")
fiDest = raw_input("Nom du fichier destinataire : ")
fs = open(fiSource, 'r')
fd = open(fiDest, 'w')
 
 
# On lit d'abord la première ligne :
ch1 = fs.readline()
# On lit ensuite les suivantes, en les fusionnant si nécessaire :
while 1:
    ch2 = fs.readline()
    if ch2 == "":
        break
    # Si la chaîne lue commence par une majuscule, on transcrit
    # la précédente dans le fichier destinataire, et on la
    # remplace par celle que l'on vient de lire :
    if ch2[0] >= "A" and ch2[0] <= "Z":
        fd.write(ch1)
        ch1 = ch2
    # Sinon, on la fusionne avec la précédente :
    else:
        ch1 = ch1[:-1] + " " + ch2
        # (veiller à enlever de ch1 le caractère de fin de ligne)
 
fd.write(ch1)        # ne pas oublier de transcrire la dernière !
fd.close()    
fs.close()

Exercice 10.25 (caractéristiques de sphères) :

 
Sélectionnez
# Le fichier de départ est un fichier <texte> dont chaque ligne contient
# un nombre réel (encodé sous la forme d'une chaîne de caractères)    
 
from math import pi
 
def caractSphere(d):
    "renvoie les caractéristiques d'une sphère de diamètre d"
    d = float(d)        # conversion de l'argument (=chaîne) en réel
    r = d/2             # rayon
    ss = pi*r**2        # surface de section
    se = 4*pi*r**2      # surface extérieure
    v = 4./3*pi*r**3    # volume  (! la 1e division doit être réelle !)
    # Le marqueur de conversion %8.2f utilisé ci-dessous formate le nombre
    # affiché de manière à occuper 8 caractères au total, en arrondissant
    # de manière à conserver deux chiffres après la virgule : 
    ch = "Diam. %6.2f cm Section = %8.2f cm&#178; " % (d, ss)
    ch = ch +"Surf. = %8.2f cm&#178;. Vol. = %9.2f cm&#179;" % (se, v)
    return ch
 
fiSource = raw_input("Nom du fichier à traiter : ")
fiDest = raw_input("Nom du fichier destinataire : ")
fs = open(fiSource, 'r')
fd = open(fiDest, 'w')
while 1:
    diam = fs.readline()
    if diam == "" or diam == "\n":
        break
    fd.write(caractSphere(diam) + "\n")         # enregistrement
fd.close()
fs.close()

Exercice 10.26 :

 
Sélectionnez
# Mise en forme de données numériques
# Le fichier traité est un fichier <texte> dont chaque ligne contient un nombre
# réel (sans exposants et encodé sous la forme d'une chaîne de caractères)    
 
def arrondir(reel):
    "représentation arrondie à .0 ou .5 d'un nombre réel"
    ent = int(reel)             # partie entière du nombre
    fra = reel - ent            # partie fractionnaire
    if fra < .25 :
        fra = 0
    elif fra < .75 :
        fra = .5
    else:
        fra = 1
    return ent + fra    
 
fiSource = raw_input("Nom du fichier à traiter : ")
fiDest = raw_input("Nom du fichier destinataire : ")
fs = open(fiSource, 'r')
fd = open(fiDest, 'w')
while 1:
    ligne = fs.readline()
    if ligne == "" or ligne == "\n":
        break
    n = arrondir(float(ligne))      # conversion en <float>, puis arrondi
    fd.write(str(n) + "\n")         # enregistrement
 
fd.close()
fs.close()

Exercice 10.29 :

 
Sélectionnez
# Affichage de tables de multiplication
 
nt = [2, 3, 5, 7, 9, 11, 13, 17, 19]
 
def tableMulti(m, n):
     "renvoie n termes de la table de multiplication par m"
     ch =""
     for i in range(n):
          v = m * (i+1)               # calcul d'un des termes
          ch = ch + "M" % (v)       # formatage à 4 caractères
     return ch
 
for a in nt:
     print tableMulti(a, 15)          # 15 premiers termes seulement

Exercice 10.30 (simple parcours d'une liste) :

 
Sélectionnez
lst = ['Jean-Michel', 'Marc', 'Vanessa', 'Anne',
       'Maximilien', 'Alexandre-Benoît', 'Louise']
 
for e in lst:
     print "%s : %s caractères" % (e, len(e))
Exercice 10.31 :
# Elimination 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

Exercice 10.33 (afficher tous les jours d'une année) :

 
Sélectionnez
## 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

Exercice 10.36 :

 
Sélectionnez
# 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

Exercice 10.40 :

 
Sélectionnez
# Crible d'Eratosthè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,

Exercice 10.43 (Test du générateur de nombres aléatoires, page 141) :

 
Sélectionnez
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,

Exercice 10.44 : tirage de cartes

 
Sélectionnez
from random import randrange
 
couleurs = ['Pique', 'Trèfle', 'Carreau', 'Coeur']
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]

Exercice 10.45 : Création et consultation d'un dictionnaire

 
Sélectionnez
def consultation():
    while 1:
        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]            # consultaion proprement dite
            age, taille = item[0], item[1]
            print "Nom : %s - âge : %s ans - taille : %s m."\
                   % (nom, age, taille)          
        else:
            print "*** nom inconnu ! ***"
 
def remplissage():
    while 1:
        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)
 
dico ={}
while 1:
    choix = raw_input("Choisissez : (R)emplir - (C)onsulter - (T)erminer : ")
    if choix.upper() == 'T':
        break
    elif choix.upper() == 'R':
        remplissage()
    elif choix.upper() == 'C':
        consultation()

Exercice 10.46 : échange des clés et des valeurs dans un dictionnaire

 
Sélectionnez
def inverse(dico):
    "Construction d'un nouveau dico, pas à pas"
    dic_inv ={} 
    for cle in dico:
        item = dico[cle]  
        dic_inv[item] = cle
 
    return dic_inv
 
 
# programme test :
 
dico = {'Computer':'Ordinateur',
        'Mouse':'Souris',
        'Keyboard':'Clavier',
        'Hard disk':'Disque dur',
        'Screen':'Ecran'}
 
print dico
print inverse(dico)

Exercice 10.47 : histogramme

 
Sélectionnez
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

Exercice 10.48 :

 
Sélectionnez
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]

Exercice 10.49 :

 
Sélectionnez
# 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. 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

Exercice 10.50 : Sauvegarde d'un dictionnaire (complément de l'ex. 10.45).

 
Sélectionnez
def enregistrement():
    fich = raw_input("Entrez le nom du fichier de sauvegarde : ")
    ofi = open(fich, "w")
    # parcours du dictionnaire entier, converti au préalable en une liste :
    for cle, valeur in dico.items(): 
        # utilisation du formatage des chaînes pour créer l'enregistrement :
        ofi.write("%s@%s#%s\n" % (cle, valeur[0], valeur[1]))
    ofi.close()
 
def lectureFichier():
    fich = raw_input("Entrez le nom du fichier de sauvegarde : ")
    try:
        ofi = open(fich, "r")
    except:
        print "*** fichier inexistant ***"
        return
 
    while 1:
        ligne = ofi.readline()
        if ligne =='':              # détection de la fin de fichier
            break
        enreg = ligne.split("@")    # restitution d'une liste [clé,valeur]
        cle = enreg[0]
        valeur = enreg[1][:-1]      # élimination du caractère de fin de ligne
        data = valeur.split("#")    # restitution d'une liste [âge, taille]
        age, taille = int(data[0]), float(data[1])
        dico[cle] = (age, taille)   # reconstitution du dictionnaire
    ofi.close()

Ces deux fonctions peuvent être appelées respectivement à la fin et au début du programme principal, comme dans l'exemple ci-dessous :

 
Sélectionnez
dico ={}
lectureFichier()        
while 1:
    choix = raw_input("Choisissez : (R)emplir - (C)onsulter - (T)erminer : ")
    if choix.upper() == 'T':
        break
    elif choix.upper() == 'R':
        remplissage()
    elif choix.upper() == 'C':
        consultation()
enregistrement()

Exercice 10.51 : Contrôle du flux d'exécution à l'aide d'un dictionnaire

Cet exercice complète le précédent. On ajoute encore deux petites fonctions, et on réécrit le corps principal du programme pour diriger le flux d'exécution en se servant d'un dictionnaire :

 
Sélectionnez
def sortie():
    print "*** Job terminé ***"
    return 1                        # afin de provoquer la sortie de la boucle 
 
def autre():
    print "Veuillez frapper R, A, C, S ou T, svp."
 
 
dico ={}
fonc ={"R":lectureFichier, "A":remplissage, "C":consultation,
       "S":enregistrement, "T":sortie}
while 1:
    choix = raw_input("Choisissez :\n" +\
    "(R)écupérer un dictionnaire préexistant sauvegardé dans un fichier\n" +\
    "(A)jouter des données au dictionnaire courant\n" +\
    "(C)onsulter le dictionnaire courant\n" +\
    "(S)auvegarder le dictionnaire courant dans un fichier\n" +\
    "(T)erminer : ")
    # l'instruction ci-dessous appelle une fonction différente pour
    # chaque choix, par l'intermédiaire du dictionnaire <fonc> :
    if fonc.get(choix, autre)():
        break
    # Rem : toutes les fonctions appelées ici renvoient <None> par défaut,
    #       sauf la fonction sortie() qui renvoie 1 => sortie de la boucle

Exercice 12.1 :

 
Sélectionnez
class Domino:
    def __init__(self, pa, pb):
        self.pa, self.pb = pa, pb
 
    def affiche_points(self):
        print "face A :", self.pa,
        print "face B :", self.pb
 
    def valeur(self):
        return self.pa + self.pb
 
# Programme de test :
 
d1 = Domino(2,6)
d2 = Domino(4,3)
 
d1.affiche_points()
d2.affiche_points()
 
print "total des points :", d1.valeur() + d2.valeur() 
 
liste_dominos = []
for i in range(7):
    liste_dominos.append(Domino(6, i))
 
vt =0
for i in range(7):
    liste_dominos[i].affiche_points()
    vt = vt + liste_dominos[i].valeur()
 
print "valeur totale des points", vt

Exercice 12.3 :

 
Sélectionnez
class Voiture:
    def __init__(self, marque = 'Ford', couleur = 'rouge'):
        self.couleur = couleur
        self.marque = marque
        self.pilote = 'personne'
        self.vitesse = 0
 
    def accelerer(self, taux, duree):
        if self.pilote =='personne':
            print "Cette voiture n'a pas de conducteur !"
        else:    
            self.vitesse = self.vitesse + taux * duree
 
    def choix_conducteur(self, nom):
        self.pilote = nom    
 
    def affiche_tout(self):
            print "%s %s pilotée par %s, vitesse = %s m/s" % \
            (self.marque, self.couleur, self.pilote, self.vitesse)     
 
a1 = Voiture('Peugeot', 'bleue')
a2 = Voiture(couleur = 'verte')
a3 = Voiture('Mercedes')
a1.choix_conducteur('Roméo')
a2.choix_conducteur('Juliette')
a2.accelerer(1.8, 12)
a3.accelerer(1.9, 11)
a2.affiche_tout()
a3.affiche_tout()

Exercice 12.4 :

 
Sélectionnez
class Satellite:
    def __init__(self, nom, masse =100, vitesse =0):
        self.nom, self.masse, self.vitesse = nom, masse, vitesse
 
    def impulsion(self, force, duree):
        self.vitesse = self.vitesse + force * duree / self.masse
 
    def energie(self):
        return self.masse * self.vitesse**2 / 2    
 
    def affiche_vitesse(self):
        print "Vitesse du satellite %s = %s m/s" \
                          % (self.nom, self.vitesse)
 
# Programme de test :
 
s1 = Satellite('Zoé', masse =250, vitesse =10)
 
s1.impulsion(500, 15)
s1.affiche_vitesse()
print s1.energie()
s1.impulsion(500, 15)
s1.affiche_vitesse()
print s1.energie()

Exercices 12.5-12.6 (classes de cylindres et de cônes) :

 
Sélectionnez
# Classes dérivées - polymorphisme
 
class Cercle:
    def __init__(self, rayon):
        self.rayon = rayon
 
    def surface(self):
        return 3.1416 * self.rayon**2
 
class Cylindre(Cercle):
    def __init__(self, rayon, hauteur):
        Cercle.__init__(self, rayon)
        self.hauteur = hauteur
 
    def volume(self):
        return self.surface()*self.hauteur
 
        # la méthode surface() est héritée de la classe parente
 
class Cone(Cylindre):
    def __init__(self, rayon, hauteur):
        Cylindre.__init__(self, rayon, hauteur)
 
    def volume(self):
        return Cylindre.volume(self)/3
 
        # cette nouvelle méthode volume() remplace celle que
        # l'on a héritée de la classe parente (exemple de polymorphisme)
 
cyl = Cylindre(5, 7)
print cyl.surface()
print cyl.volume()
 
co = Cone(5,7)
print co.surface()
print co.volume()

Exercice 12.7 :

 
Sélectionnez
# Tirage de cartes
 
from random import randrange
 
class JeuDeCartes:
    """Jeu de cartes"""
    # attributs de classe (communs à toutes les instances) :
    couleur = ('Pique', 'Trèfle', 'Carreau', 'Coeur')
    valeur = (0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'valet', 'dame', 'roi', 'as')
 
    def __init__(self):
        "Construction de la liste des 52 cartes"
        self.carte =[]          
        for coul in range(4):
            for val in range(13):
                self.carte.append((val +2, coul))   # la valeur commence à 2
 
    def nom_carte(self, c):
        "Renvoi du nom de la carte c, en clair"
        return "%s de %s" % (self.valeur[c[0]], self.couleur[c[1]])
 
    def battre(self):
        "Mélange des cartes"
        t = len(self.carte)             # nombre de cartes restantes
        # pour mélanger, on procède à un nombre d'échanges équivalent :
        for i in range(t):
            # tirage au hasard de 2 emplacements dans la liste :         
            h1, h2 = randrange(t), randrange(t)     
            # échange des cartes situées à ces emplacements :
            self.carte[h1], self.carte[h2] = self.carte[h2], self.carte[h1]
 
    def tirer(self):
        "Tirage de la première carte de la pile"
        t = len(self.carte)             # vérifier qu'il reste des cartes 
        if t >0:                        
            carte = self.carte[0]       # choisir la première carte du jeu
            del(self.carte[0])          # la retirer du jeu
            return carte                # en renvoyer copie au prog. appelant
        else:
            return None                 # facultatif
 
 
### Programme test :
 
if __name__ == '__main__':
    jeu = JeuDeCartes()                 # instanciation d'un objet
    jeu.battre()                        # mélange des cartes
    for n in range(53):                 # tirage des 52 cartes : 
        c = jeu.tirer()  		 
        if c == None:                   # il ne reste aucune carte
            print 'Terminé !'           # dans la liste
        else:
            print jeu.nom_carte(c)      # valeur et couleur de la carte

Exercice 12.8 :

(On supposera que l'exercice précédent a été sauvegardé sous le nom cartes.py)

 
Sélectionnez
# Bataille de de cartes
 
from cartes import JeuDeCartes
 
jeuA = JeuDeCartes()        # instanciation du premier jeu      
jeuB = JeuDeCartes()        # instanciation du second jeu      
jeuA.battre()               # mélange de chacun
jeuB.battre()
pA, pB = 0, 0               # compteurs de points des joueurs A et B
 
# tirer 52 fois une carte de chaque jeu :
for n in range(52):         
    cA, cB = jeuA.tirer(), jeuB.tirer()
    vA, vB = cA[0], cB[0]   # valeurs de ces cartes
    if vA > vB:
        pA += 1
    elif vB > vA:
        pB += 1             # (rien ne se passe si vA = vB)
    # affichage des points successifs et des cartes tirées :
    print "%s * %s ==> %s * %s" % (jeuA.nom_carte(cA), jeuB.nom_carte(cB), pA, pB) 
 
print "le joueur A obtient %s points, le joueur B en obtient %s." % (pA, pB)

Exercice 13.6 :

 
Sélectionnez
from Tkinter import *
 
def cercle(can, x, y, r, coul ='white'):
    "dessin d'un cercle de rayon <r> en <x,y> dans le canevas <can>"
    can.create_oval(x-r, y-r, x+r, y+r, fill =coul)
 
class Application(Tk):
    def __init__(self):
        Tk.__init__(self)        # constructeur de la classe parente
        self.can =Canvas(self, width =475, height =130, bg ="white")
        self.can.pack(side =TOP, padx =5, pady =5)
        Button(self, text ="Train", command =self.dessine).pack(side =LEFT)
        Button(self, text ="Hello", command =self.coucou).pack(side =LEFT)
        Button(self, text ="Ecl34", command =self.eclai34).pack(side =LEFT)
 
    def dessine(self):
        "instanciation de 4 wagons dans le canevas"
        self.w1 = Wagon(self.can, 10, 30)
        self.w2 = Wagon(self.can, 130, 30, 'dark green')
        self.w3 = Wagon(self.can, 250, 30, 'maroon')
        self.w4 = Wagon(self.can, 370, 30, 'purple')
 
    def coucou(self):
        "apparition de personnages dans certaines fenêtres"
        self.w1.perso(3)        # 1er wagon, 3e fenêtre
        self.w3.perso(1)        # 3e wagon, 1e fenêtre
        self.w3.perso(2)        # 3e wagon, 2e fenêtre
        self.w4.perso(1)        # 4e wagon, 1e fenêtre
 
    def eclai34(self):
        "allumage de l'éclairage dans les wagons 3 & 4"
        self.w3.allumer()
        self.w4.allumer()
 
class Wagon:
    def __init__(self, canev, x, y, coul ='navy'):
        "dessin d'un petit wagon en <x,y> dans le canevas <canev>"
        # mémorisation des paramètres dans des variables d'instance :
        self.canev, self.x, self.y = canev, x, y
        # rectangle de base : 95x60 pixels :
        canev.create_rectangle(x, y, x+95, y+60, fill =coul)
        # 3 fenêtres de 25x40 pixels, écartées de 5 pixels :
        self.fen =[]    # pour mémoriser les réf. des fenêtres 
        for xf in range(x +5, x +90, 30):
            self.fen.append(canev.create_rectangle(xf, y+5,
                                xf+25, y+40, fill ='black'))
        # 2 roues de rayon égal à 12 pixels  :
        cercle(canev, x+18, y+73, 12, 'gray')
        cercle(canev, x+77, y+73, 12, 'gray')
 
    def perso(self, fen):
        "apparition d'un petit personnage à la fenêtre <fen>"
        # calcul des coordonnées du centre de chaque fenêtre :
        xf = self.x + fen*30 -12
        yf = self.y + 25
        cercle(self.canev, xf, yf, 10, "pink")      # visage
        cercle(self.canev, xf-5, yf-3, 2)   # oeil gauche        
        cercle(self.canev, xf+5, yf-3, 2)   # oeil droit
        cercle(self.canev, xf, yf+5, 3)     # bouche
 
    def allumer(self):
        "déclencher l'éclairage interne du wagon"
        for f in self.fen:
            self.canev.itemconfigure(f, fill ='yellow')
 
Application().app.mainloop()

Exercice 13.21 :

 
Sélectionnez
# Dictionnaire de couleurs
Image non disponible
 
Sélectionnez
from Tkinter import *
# Module donnant accès aux boîtes de dialogue standard pour
# la recherche de fichiers sur disque :
from tkFileDialog import asksaveasfile, askopenfile
 
class Application(Frame):
    '''Fenêtre d'application'''
    def __init__(self):
        Frame.__init__(self)
        self.master.title("Création d'un dictionnaire de couleurs")
 
        self.dico ={}       # création du dictionnaire
 
        # Les widgets sont regroupés dans deux cadres (Frames) : 
        frSup =Frame(self)      # cadre supérieur contenant 6 widgets 
        Label(frSup, text ="Nom de la couleur :",
              width =20).grid(row =1, column =1)
        self.enNom =Entry(frSup, width =25)        # champ d'entrée pour
        self.enNom.grid(row =1, column =2)         # le nom de la couleur
        Button(frSup, text ="Existe déjà ?", width =12,
               command =self.chercheCoul).grid(row =1, column =3)
        Label(frSup, text ="Code hexa. corresp. :",
              width =20).grid(row =2, column =1)
        self.enCode =Entry(frSup, width =25)        # champ d'entrée pour
        self.enCode.grid(row =2, column =2)         # le code hexa.
        Button(frSup, text ="Test", width =12,
               command =self.testeCoul).grid(row =2, column =3)
        frSup.pack(padx =5, pady =5)
 
        frInf =Frame(self)      # cadre inférieur contenant le reste
        self.test = Label(frInf, bg ="white", width =45,    # zone de test
                          height =7, relief = SUNKEN)
        self.test.pack(pady =5)   
        Button(frInf, text ="Ajouter la couleur au dictionnaire",
               command =self.ajouteCoul).pack()
        Button(frInf, text ="Enregistrer le dictionnaire", width =25,
               command =self.enregistre).pack(side = LEFT, pady =5)
        Button(frInf, text ="Restaurer le dictionnaire", width =25,
               command =self.restaure).pack(side =RIGHT, pady =5)
        frInf.pack(padx =5, pady =5)
        self.pack()        
 
    def ajouteCoul(self):
        "ajouter la couleur présente au dictionnaire"
        if self.testeCoul() ==0:        # une couleur a-t-elle été définie ?
            return       
        nom = self.enNom.get()
        if len(nom) >1:                 # refuser les noms trop petits
            self.dico[nom] =self.cHexa
        else:
            self.test.config(text ="%s : nom incorrect" % nom, bg ='white') 
 
    def chercheCoul(self):
        "rechercher une couleur déjà inscrite au dictionnaire"
        nom = self.enNom.get()
        if self.dico.has_key(nom):
            self.test.config(bg =self.dico[nom], text ="")
        else:
            self.test.config(text ="%s : couleur inconnue" % nom, bg ='white') 
 
    def testeCoul(self):
        "vérifier la validité d'un code hexa. - afficher la couleur corresp."
        try:
            self.cHexa =self.enCode.get()
            self.test.config(bg =self.cHexa, text ="")
            return 1
        except:
            self.test.config(text ="Codage de couleur incorrect", bg ='white')
            return 0
 
    def enregistre(self):
        "enregistrer le dictionnaire dans un fichier texte"
        # Cette méthode utilise une boîte de dialogue standard pour la
        # sélection d'un fichier sur disque. Tkinter fournit toute une série
        # de fonctions associées à ces boîtes, dans le module tkFileDialog.
        # La fonction ci-dessous renvoie un objet-fichier ouvert en écriture :
        ofi =asksaveasfile(filetypes=[("Texte",".txt"),("Tous","*")]) 
        for clef, valeur in self.dico.items():
            ofi.write("%s %s\n" % (clef, valeur))
        ofi.close()
 
    def restaure(self):
        "restaurer le dictionnaire à partir d'un fichier de mémorisation"
        # La fonction ci-dessous renvoie un objet-fichier ouvert en lecture :
        ofi =askopenfile(filetypes=[("Texte",".txt"),("Tous","*")]) 
        lignes = ofi.readlines()
        for li in lignes:
            cv = li.split()     # extraction de la clé et la valeur corresp.
            self.dico[cv[0]] = cv[1]
        ofi.close()
 
if __name__ == '__main__':
    Application().mainloop()

Exercice 13.22 (variante 3) :

 
Sélectionnez
from Tkinter import *
from random import randrange
from math import sin, cos, pi
 
class FaceDom:
    def __init__(self, can, val, pos, taille =70):
        self.can =can        
        x, y, c = pos[0], pos[1], taille/2
        self. carre = can.create_rectangle(x -c, y-c, x+c, y+c,
                                           fill ='ivory', width =2)
        d = taille/3         
        # disposition des points sur la face, pour chacun des 6 cas :
        self.pDispo = [((0,0),),
                       ((-d,d),(d,-d)),
                       ((-d,-d), (0,0), (d,d)),
                       ((-d,-d),(-d,d),(d,-d),(d,d)),
                       ((-d,-d),(-d,d),(d,-d),(d,d),(0,0)),
                       ((-d,-d),(-d,d),(d,-d),(d,d),(d,0),(-d,0))]
 
        self.x, self.y, self.dim = x, y, taille/15
        self.pList =[]      # liste contenant les points de cette face 
        self.tracer_points(val)
 
    def tracer_points(self, val):
        # créer les dessins de points correspondant à la valeur val :
        disp = self.pDispo[val -1]
        for p in disp:
            self.cercle(self.x +p[0], self.y +p[1], self.dim, 'red')
        self.val = val
 
    def cercle(self, x, y, r, coul):
        self.pList.append(self.can.create_oval(x-r, y-r, x+r, y+r, fill=coul))
 
    def effacer(self, flag =0):
        for p in self.pList:
            self.can.delete(p)
        if flag:
            self.can.delete(self.carre)
 
class Projet(Frame):
    def __init__(self, larg, haut):
        Frame.__init__(self)
        self.larg, self.haut = larg, haut
        self.can = Canvas(self, bg='dark green', width =larg, height =haut)
        self.can.pack(padx =5, pady =5)
        # liste des boutons à installer, avec leur gestionnaire :
        bList = [("A", self.boutA), ("B", self.boutB),
                 ("C", self.boutC), ("Quitter", self.boutQuit)]
        bList.reverse()         # inverser l'ordre de la liste
        for b in bList:
            Button(self, text =b[0], command =b[1]).pack(side =RIGHT, padx=3)
        self.pack()
        self.des =[]            # liste qui contiendra les faces de dés
        self.actu =0            # réf. du dé actuellement sélectionné
 
    def boutA(self):
        if len(self.des):
            return              # car les dessins existent déjà !
        a, da = 0, 2*pi/13
        for i in range(13):
            cx, cy = self.larg/2, self.haut/2
            x = cx + cx*0.75*sin(a)             # pour disposer en cercle,
            y = cy + cy*0.75*cos(a)             # on utilise la trigono !
            self.des.append(FaceDom(self.can, randrange(1,7) , (x,y), 65))
            a += da
 
    def boutB(self):
        # incrémenter la valeur du dé sélectionné. Passer au suivant :
        v = self.des[self.actu].val
        v = v % 6
        v += 1        
        self.des[self.actu].effacer()
        self.des[self.actu].tracer_points(v)
        self.actu += 1
        self.actu = self.actu % 13
 
    def boutC(self):
        for i in range(len(self.des)):
            self.des[i].effacer(1)
        self.des =[]
        self.actu =0
 
    def boutQuit(self):
        self.master.destroy()
 
Projet(600, 600).mainloop()

Exercice 16.1 (Création de la base de données "musique") :

 
Sélectionnez
import gadfly
 
connex = gadfly.gadfly()
connex.startup("musique","E:/Python/essais/gadfly")
cur = connex.cursor()
requete = "create table compositeurs (comp varchar, a_naiss integer,\
           a_mort integer)" 
cur.execute(requete)
requete = "create table oeuvres (comp varchar, titre varchar,\
           duree integer, interpr varchar)" 
cur.execute(requete)
 
print "Entrée des enregistrements, table des compositeurs :"
while 1:
    nm = raw_input("Nom du compositeur (<Enter> pour terminer) : ")
    if nm =='':
        break
    an = raw_input("Année de naissance : ")
    am = raw_input("Année de mort : ")
    requete ="insert into compositeurs(comp, a_naiss, a_mort) values \
                 ('%s', %s, %s)" % (nm, an, am)
    cur.execute(requete)
# Affichage des données entrées, pour vérification :
cur.execute("select * from compositeurs")
print cur.pp()
 
print "Entrée des enregistrements, table des oeuvres musicales :"
while 1:
    nom = raw_input("Nom du compositeur (<Enter> pour terminer) : ")
    if nom =='':
        break
    tit = raw_input("Titre de l'oeuvre : ")
    dur = raw_input("durée (minutes) : ")
    int = raw_input("interprète principal : ")
    requete ="insert into oeuvres(comp, titre, duree, interpr) values \
                 ('%s', '%s', %s, '%s')" % (nom, tit, dur, int)
    cur.execute(requete)
# Affichage des données entrées, pour vérification :
cur.execute("select * from oeuvres")
print cur.pp()
 
connex.commit()

Exercice 18.2 :

 
Sélectionnez
#####################################
# Bombardement d'une cible mobile   #
# (C) G. Swinnen - Avril 2004 - GPL #
#####################################
 
from Tkinter import *
from math import sin, cos, pi
from random import randrange
from threading import Thread
 
class Canon:
    """Petit canon graphique"""
    def __init__(self, boss, num, x, y, sens):
        self.boss = boss            # référence du canevas
        self.num = num              # n° du canon dans la liste
        self.x1, self.y1 = x, y     # axe de rotation du canon
        self.sens = sens            # sens de tir (-1:gauche, +1:droite)
        self.lbu = 30               # longueur de la buse
        # dessiner la buse du canon (horizontale) :
        self.x2, self.y2 = x + self.lbu * sens, y
        self.buse = boss.create_line(self.x1, self.y1,
                                     self.x2, self.y2, width =10)
        # dessiner le corps du canon (cercle de couleur) :
        self.rc = 15                # rayon du cercle 
        self.corps = boss.create_oval(x -self.rc, y -self.rc, x +self.rc,
                                      y +self.rc, fill ='black')
        # pré-dessiner un obus (au départ c'est un simple point) :
        self.obus = boss.create_oval(x, y, x, y, fill='red')
        self.anim = 0
        # retrouver la largeur et la hauteur du canevas :
        self.xMax = int(boss.cget('width'))
        self.yMax = int(boss.cget('height'))
 
    def orienter(self, angle):
        "régler la hausse du canon"
        # rem : le paramètre <angle> est reçu en tant que chaîne.
        # il faut donc le traduire en réel, puis le convertir en radians :
        self.angle = float(angle)*2*pi/360      
        self.x2 = self.x1 + self.lbu * cos(self.angle) * self.sens
        self.y2 = self.y1 - self.lbu * sin(self.angle)
        self.boss.coords(self.buse, self.x1, self.y1, self.x2, self.y2)
 
    def feu(self):
        "déclencher le tir d'un obus"
        # référence de l'objet cible :
        self.cible = self.boss.master.cible
        if self.anim ==0:
            self.anim =1
            # position de départ de l'obus (c'est la bouche du canon) :
            self.xo, self.yo = self.x2, self.y2
            v = 20              # vitesse initiale
            # composantes verticale et horizontale de cette vitesse :
            self.vy = -v *sin(self.angle)
            self.vx = v *cos(self.angle) *self.sens
            self.animer_obus()
 
    def animer_obus(self):
        "animer l'obus (trajectoire balistique)"
        # positionner l'obus, en re-définissant ses coordonnées :
        self.boss.coords(self.obus, self.xo -3, self.yo -3,
                                    self.xo +3, self.yo +3)
        if self.anim >0:
            # calculer la position suivante :
            self.xo += self.vx
            self.yo += self.vy
            self.vy += .5
            self.test_obstacle()        # a-t-on atteint un obstacle ?
            self.boss.after(1, self.animer_obus)
        else:
            # fin de l'animation :
            self.boss.coords(self.obus, self.x1, self.y1, self.x1, self.y1) 
 
    def test_obstacle(self):
        "évaluer si l'obus a atteint une cible ou les limites du jeu"
        if self.yo >self.yMax or self.xo <0 or self.xo >self.xMax:
            self.anim =0
            return
        if self.yo > self.cible.y -3 and self.yo < self.cible.y +18 \
        and self.xo > self.cible.x -3 and self.xo < self.cible.x +43:
            # dessiner l'explosion de l'obus (cercle orange) :
            self.explo = self.boss.create_oval(self.xo -10,
                         self.yo -10, self.xo +10, self.yo +10,
                         fill ='orange', width =0)
            self.boss.after(150, self.fin_explosion)
            self.anim =0
 
    def fin_explosion(self):
        "effacer le cercle d'explosion - gérer le score"
        self.boss.delete(self.explo)
        # signaler le succès à la fenêtre maîtresse :
        self.boss.master.goal()        
 
class Pupitre(Frame):
    """Pupitre de pointage associé à un canon""" 
    def __init__(self, boss, canon):
        Frame.__init__(self, bd =3, relief =GROOVE)
        self.score =0
        s =Scale(self, from_ =88, to =65,
                 troughcolor ='dark grey',
                 command =canon.orienter)
        s.set(45)                       # angle initial de tir
        s.pack(side =LEFT)
        Label(self, text ='Hausse').pack(side =TOP, anchor =W, pady =5)        
        Button(self, text ='Feu !', command =canon.feu).\
                                    pack(side =BOTTOM, padx =5, pady =5)
        Label(self, text ="points").pack()
        self.points =Label(self, text=' 0 ', bg ='white')
        self.points.pack()
        # positionner à gauche ou à droite suivant le sens du canon :
        gd =(LEFT, RIGHT)[canon.sens == -1]
        self.pack(padx =3, pady =5, side =gd)
 
    def attribuerPoint(self, p):
        "incrémenter ou décrémenter le score"
        self.score += p
        self.points.config(text = ' %s ' % self.score)
 
class Cible:
    """objet graphique servant de cible"""
    def __init__(self, can, x, y):
        self.can = can             # référence du canevas
        self.x, self.y = x, y
        self.cible = can.create_oval(x, y, x+40, y+15, fill ='purple')
 
    def deplacer(self, dx, dy):
        "effectuer avec la cible un déplacement dx,dy" 
        self.can.move(self.cible, dx, dy)
        self.x += dx
        self.y += dy
        return self.x, self.y
 
class Thread_cible(Thread):
    """objet thread gérant l'animation de la cible"""
    def __init__(self, app, cible):
        Thread.__init__(self)
        self.cible = cible          # objet à déplacer
        self.app = app              # réf. de la fenêtre d'application
        self.sx, self.sy = 6, 3     # incréments d'espace et de
        self.dt =300                # temps pour l'animation (ms)
 
    def run(self):
        "animation, tant que la fenêtre d'application existe" 
        x, y = self.cible.deplacer(self.sx, self.sy)
        if x > self.app.xm -50 or x < self.app.xm /5:
                self.sx = -self.sx
        if y < self.app.ym /2 or y > self.app.ym -20:
                self.sy = -self.sy
        if self.app != None:
            self.app.after(int(self.dt), self.run)
 
    def stop(self):
        "fermer le thread si la fenêtre d'application est refermée"
        self.app =None
 
    def accelere(self):
        "accélérer le mouvement"
        self.dt /= 1.5
 
class Application(Frame):
    def __init__(self):
        Frame.__init__(self)
        self.master.title('<<< Tir sur cible mobile >>>')
        self.pack()
        self.xm, self.ym = 600, 500
        self.jeu = Canvas(self, width =self.xm, height =self.ym,
                          bg ='ivory', bd =3, relief =SUNKEN)
        self.jeu.pack(padx =4, pady =4, side =TOP)
 
        # Instanciation d'un canon et d'un pupitre de pointage :
        x, y = 30, self.ym -20
        self.gun =Canon(self.jeu, 1, x, y, 1)
        self.pup =Pupitre(self, self.gun)
 
        # instanciation de la cible mobile :
        self.cible = Cible(self.jeu, self.xm/2, self.ym -25)
        # animation de la cible mobile, sur son propre thread :
        self.tc = Thread_cible(self, self.cible)
        self.tc.start()
        # arrêter tous les threads lorsque l'on ferme la fenêtre :
        self.bind('<Destroy>',self.fermer_threads)
 
    def goal(self):
        "la cible a été touchée"
        self.pup.attribuerPoint(1)
        self.tc.accelere()
 
    def fermer_threads(self, evt):
        "arrêter le thread d'animation de la cible"
        self.tc.stop()
 
if __name__ =='__main__':
    Application().mainloop()

19-10. Annexes extraites de « How to think like a computer scientist »

Suivant les termes de la GNU Free Documentation licence (voir p. 361), les annexes qui suivent doivent obligatoirement accompagner telles quelles toute distribution du texte original, que celui-ci ait été modifié (traduit, par exemple) ou non.

19-10-1. Contributor list

by Jeffrey Elkner

Perhaps the most exciting thing about a free content textbook is the possibility it creates for those using the book to collaborate in its development. I have been delighted by the many responses, suggestions, corrections, and words of encouragement I have received from people who have found this book to be useful, and who have taken the time to let me know about it.

Unfortunately, as a busy high school teacher who is working on this project in my spare time (what little there is of it ;-), I have been neglectful in giving credit to those who have helped with the book. I always planned to add an "Acknowlegdements" sections upon completion of the first stable version of the book, but as time went on it became increasingly difficult to even track those who had contributed.

Upon seeing the most recent version of Tony Kuphaldt's wonderful free text, "Lessons in Electric Circuits", I got the idea from him to create an ongoing "Contributor List" page which could be easily modified to include contributors as they come in.

My only regret is that many earlier contributors might be left out. I will begin as soon as possible to go back through old emails to search out the many wonderful folks who have helped me in this endeavour. In the mean time, if you find yourself missing from this list, please accept my humble apologies and drop me an email at jeff@elkner.net to let me know about my oversight.

And so, without further delay, here is a listing of the contributors:

Lloyd Hugh Allen

Lloyd sent in a correction to section 8.4. He can be reached at: lha2@columbia.edu

Yvon Boulianne

Yvon sent in a correction of a logical error in Chapter 5. She can be reached at: mystic@monuniverse.net

Fred Bremmer

Fred submitted a correction in section 2.1. He can be reached at: Fred.Bremmer@ubc.cu Jonah Cohen

Jonah wrote the Perl scripts to convert the LaTeX source for this book into beautiful HTML. His Web page is jonah.ticalc.org and his email is JonahCohen@aol.com Michael Conlon

Michael sent in a grammer correction in Chapter 2 and an improvement in style in Chapter 1, and he initiated discussion on the technical aspects of interpreters. Michael can be reached at:

michael.conlon@sru.edu

Courtney Gleason

Courtney and Katherine Smith created the first version of horsebet.py, which is used as the case study for the last chapters of the book. Courtney can be reached at: orion1558@aol.com

Lee Harr

Lee submitted corrections for sections 10.1 and 11.5. He can be reached at: missive@linuxfreemail.com James Kaylin

James is a student using the text. He has submitted numerous corrections. James can be reached by email at: Jamarf@aol.com

David Kershaw

David fixed the broken catTwice function in section 3.10. He can be reached at: david_kershaw@merck.com

Eddie Lam

Eddie has sent in numerous corrections to Chapters 1, 2, and 3. He also fixed the Makefile so that it creates an index the first time it is run and helped us set up a versioning scheme. Eddie can be reached at: nautilus@yoyo.cc.monash.edu.au

Man-Yong Lee Man-Yong sent in a correction to the example code in section 2.4. He can be reaced at: yong@linuxkorea.co.kr

David Mayo

While he didn't mean to hit us over the head with it, David Mayo pointed out that the word "unconsciously" in chapter 1 needed to be changed to "subconsciously". David can be reached at: bdbear44@netscape.net

Chris McAloon

Chris sent in several corrections to sections 3.9 and 3.10. He can be reached at: cmcaloon@ou.edu

Matthew J. Moelter

Matthew has been a long-time contributor who sent in numerous corrections and suggestions to the book. He can be reached at: mmoelter@calpoly.edu

Simon Dicon Montford

Simon reported a missing function definition and several typos in Chapter 3. He also found errors in the increment function in Chapter 13. He can be reached at: dicon@bigfoot.com

John Ouzts

John sent in a correction to the "return value" definition in Chapter 3. He can be reached at: jouzts@bigfoot.com

Kevin Parks

Kevin sent in valuable comments and suggestions as to how to improve the distribution of the book. He can be reached at: cpsoct@lycos.com

David Pool

David sent in a typo in the glossary of chapter 1, as well as kind words of encouragement. He can be reached at: pooldavid@hotmail.com

Michael Schmitt

Michael sent in a correction to the chapter on files and exceptions. He can be reached at: ipv6_128@yahoo.com

Paul Sleigh

Paul found an error in Chapter 7 and a bug in Jonah Cohen's Perl script that generates HTML from LaTeX. He can be reached at: bat@atdot.dotat.org

Christopher Smith

Chris is a computer science teacher at the Blake School in Minnesota who teaches Python to his beginning students. He can be reached at: csmith@blakeschool.org or smiles@saysomething.com

Katherine Smith

Katherine and Courtney Gleason created the first version of horsebet.py, which is used as the case study for the last chapters of the book. Katherine can be reached at: kss_0326@yahoo.com

Craig T. Snydal

Craig is testing the text in a course at Drew University. He has contributed several valuable suggestions and corrections, and can be reached at: csnydal@drew.edu

Ian Thomas

Ian and his students are using the text in a programming course. They are the first ones to test the chapters in the latter half of the book, and they have make numerous corrections and suggestions. Ian can be reached at: ithomas@sd70.bc.ca

Keith Verheyden

Keith made correction in Section 3.11 and can be reached at: kverheyd@glam.ac.uk

Chris Wrobel

Chris made corrections to the code in the chapter on file I/O and exceptions. He can be reached at: ferz980@yahoo.com

Moshe Zadka

Moshe has made invaluable contributions to this project. In addition to writing the first draft of the chapter on Dictionaries, he provided continual guidance in the early stages of the book. He can be reached at: moshez@math.huji.ac.il

19-10-2. Preface

by J. Elkner

This book owes its existance to the collaboration made possible by the internet and the free software movement. Its three authors, a college professor, a high school teacher, and a professional programmer, have yet to meet face to face, but we have been able to work closely together, and have been aided by many wonderful folks who have donated their time and energy to helping make it better.

What excites me most about it is that it is a testament to both the benefits and future possibilities of this kind of collaboration, the framework for which has been put in place by Richard Stallman and the Free Software Foundation.

a) How and why I came to use Python

In 1999, the College Board's Advanced Placement Computer Science exam was given in C++ for the first time. As in many high schools throughout the country, the decision to change languages had a direct impact on the computer science curriculum where I teach at Yorktown High School, in Arlington, Virginia. Up to this point, Pascal was the language of instruction in both our first year and AP courses. In keeping with past practice of giving students two years of exposure to the same language, we made the decision to switch to C++ in the first year course for the 1997-98 school year, so that we would be in step with the College Board's change for the AP course the following year.

Two years later, I was convinced that C++ was a poor choice to use for introducing students to computer science. While it is certainly a very powerful programming language, it is also an extremely difficult language to learn and teach. I found myself constantly fighting with C++'s difficult syntax and multiple ways of doing things, and I was losing many students unnecessarily as a result. Convinced there had to be a better language choice for our first year class, I went looking for an alternative to C++.

A discussion on the High School Linux Users' Group mailing list provided a solution. A thread emerged during the latter part of January, 1999 concerning the best programming language for use with first time high school computer science students. In a posting on January 30th, Brendon Ranking wrote:

I believe that Python is the best choice for any entry-level programming class. It teaches proper programming principles while being incredibly easy to learn. It is also designed to be object oriented from its inception so it doesn't have the add-on pain that both Perl and C++ suffer from...... It is also *very* widely supported and very much web-centric, as well.

I had first heard of Python a few years earlier at a Linux Install Fest, when an enthusiastic Michael McLay told me about Python's many merits. He and Brendon had now convinced me that I needed to look into Python.

Matt Ahrens, one of Yorktown's gifted students, jumped at the chance to try out Python, and in the final two months of the 1998-99 school year he not only learned the language but wrote an application called pyTicket which enabled our staff to report technology problems via the web. I knew that Matt could not have finished an application of that scale in so short a time in C++, and this accomplishment combined with Matt's positive assessment of Python suggested Python was the solution I was looking for.

b) Finding a text book

Having decided to use Python in both my introductory computer science classes the following year, the most pressing problem was the lack of an available text book.

Free content came to the rescue. Earlier in the year Richard Stallman had introduced me to Allen Downey. Both of us had written to Richard expressing an interest in developing free educational content. Allen had already written a first year computer science text book titled, How to think like a computer scientist. When I read this book I knew immediately that I wanted to use it in my class. It was the clearest and most helpful computer science text I had seen. It emphasized the processes of thought involved in programming, rather than the features of a particular language. Reading it immediately made me a better teacher.

Not only was How to think like a computer scientist an excellent book, but it was also released under a GNU public license, which meant it could be used freely and modified to meet the needs of its user. Once I decided to use Python, it occurred to me that I could translate Allen's original Java version into the new language. While I would not have been able to write a text book on my own, having Allen's book to work from made it possible for me to do so, at the same time demonstrating that the cooperative development model used so well in software could also work for educational content.

Working on this book for the last two years has been rewarding for both me and my students, and the students played a big part in the process. Since I could make instant changes whenever someone found a spelling error or difficult passage, I encouraged them to look for errors in the book by giving them a bonus point every time they found or suggested something that resulted in a change in the text. This had the double benefit of encouraging them to read the text more carefully, and of getting the text thoroughly reviewed by its most important critics, students using it to learn computer science.

For the second half of the book on object oriented programming, I knew that someone with more real programming experience than I had would be needed to do it right. The book actually sat in an unfinished state for the better part of a year until two things happened that led to its completion.

I received an email from Chris Meyers expressing interest in the book. Chris is a professional programmer who started teaching a programming course last year using Python at Lane Community College in Eugene Oregon. The prospect of teaching the course had led Chris to the book, and he started helping out with it immediately. By the end of the school year he had created a companion project on our web site at http://www.ibiblio.org/obp called Python for Fun and was working with some of my most advanced students as a master teacher, guiding them beyond the places I could take them.

c) Introducing programming with Python

The process of translating and using How to think like a computer scientist for the past two years has confirmed Python's suitability to teaching beginning students. Python greatly simplifies programming examples and makes important programming ideas easier to teach.

The first example from the text dramatically illustrates this point. It is the traditional "hello, world" program, which in the C++ version of the book looks like this:

 
Sélectionnez
#include <iostream.h>
void main()
{
cout << "Hello, world." << endl;
}

in the Python version it becomes:

 
Sélectionnez
print "Hello, World!"

Even though this is a trivial example, the advantages to Python stand out. There are no prerequisites to Yorktown's Computer Science I course, so many of the students seeing this example are looking at their first program. Some of them are undoubtedly a little nervous, having heard that computer programming is difficult to learn. The C++ version has always forced me to choose between two unsatisfying options: either to explain the #include, void main(), {, and } statements, and risk confusing or intimidating some of the students right at the start, or to tell them "just don't worry about all of that stuff now, we will talk about it later" and risk the same thing. The educational objectives at this point in the course are to introduce students to the idea of a programming statement and to get them to make their first program, thereby introducing them to the programming environment. The Python program has exactly what is needed to do these things, and nothing more.

Comparing Section 1.5 of each version of the book, where this first program is located, further illustrates what this means to the beginning student. There are thirteen paragraphs of explanation of "Hello, world" in the C++ version, in the Python version there are only two. More importantly, the missing eleven paragraphs do not deal with the "big ideas" in computer programming, but with the minutia of C++ syntax. I found this same thing happening throughout the book. Whole paragraphs simply disappear from the Python version of the text because Python's much clearer syntax renders them unnecessary.

Using a very high level language like Python allows a teacher to postpone talking about low level details of the machine until students have the background that they need to better make sense of the details. It thus creates the ability to put "first things first" pedagogically.

One of the best examples of this is the way in which Python handles variables. In C++ a variable is a name for a place which holds a thing. Variables have to be declared with types at least in part because the size of the place to which they refer needs to be predetermined. Thus the idea of a variable is bound up with the hardware of the machine. The powerful and fundamental concept of a variable is already difficult enough for beginning students (in both Computer Science and Algebra). Bytes and addresses do not help the matter. In Python a variable is a name which refers to a thing. This is a far more intuitive concept for beginning students, and one which is much closer to the meaning of variable that they learned in their math class. I had much less difficulty teaching variables this year than I did in the past, and I spent less time helping students with problems using them.

Another example of how Python aides in the teaching and learning of programming is in its syntax for functions. My students have always had a great deal of difficulty understanding functions. The main problem centers around the difference between a function definition and a function call, and the related distinction between a parameter and an argument. Python comes to the rescue with syntax that is nothing short of beautiful. Function definitions begin with the key word def, so I simply tell my students, "when you define a function, begin with def, followed by the name of the function that you are defining, when you call a function, simply call (type) out its name." Parameters go with definitions, arguments go with calls. There are no return types or parameter types or reference and value parameters to get in the way, so I am now able to teach functions in less then half the time that it previously took me, with better comprehension.

Using Python has improved the effectiveness of our computer science program for all students. I see a higher general level of success and a lower level of frustration than I experienced during the two years using C++. I move faster with better results. More students leave the course with the ability to create meaningful programs, and with the positive attitude toward the experience of programming that this engenders.

d) Building a community

I have received email every continent on the globe and from as far away as Korea from people using this book to learn or to teach programming. A user community has begun to emerge and increasing numbers of people have been contributing to the project by sending in materials for the companion web site at http://www.ibiblio.org/obp.

With the publication of the book in print form, I expect the growth in the user community to continue and accelerate. It is the emergence of this user community and the possibility it suggests for similar collaboration among educators that has been the most exciting thing for me about working on the project. By working together we can both increase the quality of materials available for our use and save valuable time. I invite you to join our community and look forward to hearing from you.


Jeffrey Elkner
Yorktown High School
Arlington, Virginia

19-10-3. GNU Free Documentation License

Version 1.1, March 2000
Copyright © 2000 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

Preamble

The purpose of this License is to make a manual, textbook, or other written document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.

This License is a kind of "copyleft," which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.

We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.

19-10-3-a-1. Applicability and Definitions

This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The "Document," below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you."

A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.

A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical, or political position regarding them.

The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License.

The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License.

A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. A copy that is not "Transparent" is called "Opaque."

Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, \LaTeX~input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML designed for human modification. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some word processors for output purposes only.

The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.

19-10-3-a-2. Verbatim Copying

You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in Section 3.

You may also lend copies, under the same conditions stated above, and you may publicly display copies.

19-10-3-a-3. Copying in Quantity

If you publish printed copies of the Document numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.

If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly accessible computer-network location containing a complete Transparent copy of the Document, free of added material, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.

It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

19-10-3-a-4. Modifications

You may copy and distribute a Modified Version of the Document under the conditions of Sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

  • Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.
  • List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has less than five).
  • State on the Title page the name of the publisher of the Modified Version, as the publisher.
  • Preserve all the copyright notices of the Document.
  • Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.
  • Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.
  • Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.
  • Include an unaltered copy of this License.
  • Preserve the section entitled "History," and its title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.
  • Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.
  • In any section entitled "Acknowledgements" or "Dedications," preserve the section's title, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.
  • Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.
  • Delete any section entitled "Endorsements." Such a section may not be included in the Modified Version.
  • Do not retitle any existing section as "Endorsements" or to conflict in title with any Invariant Section.

If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

You may add a section entitled "Endorsements," provided it contains nothing but endorsements of your Modified Version by various parties---for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.

You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front- Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.

19-10-3-a-5. Combining Documents

You may combine the Document with other documents released under this License, under the terms defined in Section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice.

The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections entitled "History" in the various original documents, forming one section entitled "History"; likewise combine any sections entitled "Acknowledgements," and any sections entitled "Dedications." You must delete all sections entitled "Endorsements."

19-10-3-a-6. Collections of Documents

You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.

19-10-3-a-7. Aggregation with Independent Works

A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, does not as a whole count as a Modified Version of the Document, provided no compilation copyright is claimed for the compilation. Such a compilation is called an "aggregate," and this License does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative works of the Document.

If the Cover Text requirement of Section 3 is applicable to these copies of the Document, then if the Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the whole aggregate.

19-10-3-a-8. Translation

Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of Section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License provided that you also include the original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail.s

19-10-3-a-9. Termination

You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense, or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

19-10-3-a-10. Future Revisions of This License

The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See
http:///www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.


précédentsommairesuivant

Licence Creative Commons
Le contenu de cet article est rédigé par Gérard Swinnen et est mis à disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transposé.
Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright © 2013 Developpez.com.