M1 Python - Corrigé du TD 1

Il fallait vraiment tester les instructions proposées une à une dans l'interpréteur, et ne surtout pas écrire un programme dans un IDE.

Le notebook jupyter permet à la fois d'utiliser l'interpréteur, d'exécuter des programmes, et de rentrer du texte formaté en markdown. Il est donc idéal pour présenter des comptes rendus de TP.

On commence par une révision rapide de la syntaxe de base.

In [1]:
# ceci est un commentaire
print (2+2) # on affiche avec "print"
4
In [2]:
print("dro"+'madaire') # les chaînes peuvent être avec des " ou des ' et on peut les concaténer
dromadaire
In [4]:
"toto" # pas besoin de print ...
Out[4]:
'toto'
In [5]:
'toto'
Out[5]:
'toto'
In [6]:
print ("a"+2*"na"+"s") # on peut aussi multiplier les chaînes
ananas
In [7]:
print ("mignonne allons voir si la rose\netc.") # on peut mettre des \quelquechose
mignonne allons voir si la rose
etc.
In [8]:
print ("ceci\test une tabulation, mais pas cela\\t.") # le caractére d'échappement est \
ceci	est une tabulation, mais pas cela\t.
In [9]:
alphabet="abcdefghijklmnopqrstuvwxyz" # on définit une variable
print (alphabet) # ça affiche l'alphabet, pas de surprise
abcdefghijklmnopqrstuvwxyz
In [10]:
len(alphabet)
Out[10]:
26
In [11]:
help(len)
Help on built-in function len in module builtins:

len(obj, /)
    Return the number of items in a container.

In [12]:
alphabet.upper() # les chaînes ont des méthodes commodes
Out[12]:
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
In [13]:
print(dir(alphabet)) # on en obtient la liste ainsi
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
In [14]:
help(dir)
Help on built-in function dir in module builtins:

dir(...)
    dir([object]) -> list of strings
    
    If called without an argument, return the names in the current scope.
    Else, return an alphabetized list of names comprising (some of) the attributes
    of the given object, and of attributes reachable from it.
    If the object supplies a method named __dir__, it will be used; otherwise
    the default dir() logic is used and returns:
      for a module object: the module's attributes.
      for a class object:  its attributes, and recursively the attributes
        of its bases.
      for any other object: its attributes, its class's attributes, and
        recursively the attributes of its class's base classes.

In [15]:
print ((2**8)%100) # 2 puissance 8, le tout modulo 100 (ça fait 56)
56
In [16]:
print (1,end= ' ') # noter le end = '' qui permet de ne pas aller à la ligne
1 
In [17]:
print (1,end=' '); print (2) # ... cette ligne affichera donc « 1 2 »
1 2

Exercice 1

Les premiers exemples du TD rappellent l'existence de + et * pour les chaînes.

In [19]:
msg = 'coin coin'
s = '* '+msg+' *'
t = '*'*len(s)+'\n'
print (t+s+'\n'+t)
*************
* coin coin *
*************

Exercice 2

dir("") permet de découvrir la méthode "center" ...

In [20]:
print ('*'*79+'\n*' + msg.center(77)+'*\n'+'*'*79)
*******************************************************************************
*                                  coin coin                                  *
*******************************************************************************

Exercice 3

... et aussi la méthode strip :

In [21]:
message="*"*13+"\n* coin coin *\n"+"*"*13
print (message)
print (message.strip('* \n'))
*************
* coin coin *
*************
coin coin

Listes ou tableaux

In [22]:
daltons=["joe","jack","william","averell"]
print (daltons[0]) # les listes, ça commence à zéro
joe
In [22]:
print (daltons[1:3]) # sous-liste de l'élément 1 inclus jusqu'au 3 exclus
['jack', 'william']
In [23]:
print (daltons[-1]) # -N = Nième élément en partant de la fin
averell
In [24]:
print (daltons[2:]) # sous-liste de l'élément 2 jusqu'à la fin
['william', 'averell']
In [25]:
daltons.sort() # tri alphabétique en place
print (daltons) # affiche la liste triée
['averell', 'jack', 'joe', 'william']
In [26]:
petit=daltons[0] # c'est "averell" vu qu'on a trié dans l'ordre alphabétique
print (petit[0]) # surprise : une chaîne, c'est une liste de caractères...
a
In [27]:
print (daltons[-2][3:]) # on peut faire ça ( remarque importante pour la suite !)

In [28]:
# Rien ... Pas d'erreur ? Pourtant, 
daltons[-2]
Out[28]:
'joe'
In [28]:
# rien à la position 3
daltons[-2][3]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-28-8c7682e472d3> in <module>()
      1 # rien à la position 3
----> 2 daltons[-2][3]

IndexError: string index out of range
In [29]:
# Mais ...
daltons[-2][3:]
# Après une position inexistante, la chaîne vide ... 
# Pour s'en rendre compte, il ne faut pas utiliser print
Out[29]:
''

Exercice 4

On s'autorise une instruction pour déterminer la longueur m de la plus courte ...

In [30]:
s1="abcdef"
s2="0123456789"
m=min(len(s1),len(s2))
# ... puis on combine "list comprehension" et tableaux (m:, :m etc)
print (''.join([s1[i]+s2[i] for i in range(m)])+s1[m:]+s2[m:])
a0b1c2d3e4f56789
In [31]:
# Autre version
print (''.join([x+y for x,y in zip(s1,s2)])+s1[m:]+s2[m:])
a0b1c2d3e4f56789
In [32]:
help(zip)
Help on class zip in module builtins:

class zip(object)
 |  zip(iter1 [,iter2 [...]]) --> zip object
 |  
 |  Return a zip object whose .__next__() method returns a tuple where
 |  the i-th element comes from the i-th iterable argument.  The .__next__()
 |  method continues until the shortest iterable in the argument sequence
 |  is exhausted and then it raises StopIteration.
 |  
 |  Methods defined here:
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __next__(self, /)
 |      Implement next(self).
 |  
 |  __reduce__(...)
 |      Return state information for pickling.

Exercice 5:

Ensuite, on peut récuperer les caractères d'indices pairs ou impairs :

In [33]:
s='a0b1c2d3e4f56789'
print (s[::2])
print (s[1::2])
abcdef68
01234579

Exercice 6

In [34]:
# Une liste de dictionnaires
daltons=[{"nom":"joe","taille":140,"caractere":"teigneux"},
         {"nom":"jack","taille":155,"caractere":"idiot"},
         {"nom":"william","taille":170,"caractere":"stupide"},
         {"nom":"averell","taille":185,"caractere":"abruti"}]
In [41]:
help(daltons.sort)
Help on built-in function sort:

sort(...) method of builtins.list instance
    L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*

In [35]:
# la liste est triée en place
daltons.sort(key=lambda x:x['taille'])
daltons
Out[35]:
[{'caractere': 'teigneux', 'nom': 'joe', 'taille': 140},
 {'caractere': 'idiot', 'nom': 'jack', 'taille': 155},
 {'caractere': 'stupide', 'nom': 'william', 'taille': 170},
 {'caractere': 'abruti', 'nom': 'averell', 'taille': 185}]
In [36]:
daltons.sort(key=lambda x:x['nom'])
daltons
Out[36]:
[{'caractere': 'abruti', 'nom': 'averell', 'taille': 185},
 {'caractere': 'idiot', 'nom': 'jack', 'taille': 155},
 {'caractere': 'teigneux', 'nom': 'joe', 'taille': 140},
 {'caractere': 'stupide', 'nom': 'william', 'taille': 170}]

Exercice 7:

On commence par écrire une fonction qui cherche un mot dans le dictionnaire.

Le dictionnaire est codé en latin1, il faut donc le passer en paramètre à la fonction open.

On peut itérer sur un fichier ouvert, il est vu comme une liste de lignes (qui se terminent donc par \n.

Plutôt que de supprimer le \n sur chaque ligne, il vaut mieux le rajouter au mot cherché.

In [37]:
def dico(w):
   with open('liste.de.mots.francais.frgut.txt',encoding='latin1') as f: # "context manager", équivalent de open-close
       if w+'\n' in f: print ("%s est dans le dictionnaire" % w)
       else: print ("%s n'est pas dans le dictionnaire" % w)

dico('zythum')
zythum est dans le dictionnaire
In [38]:
dico('déjà')
déjà est dans le dictionnaire
In [39]:
dico('gabuzomeu')
gabuzomeu n'est pas dans le dictionnaire

Une fois au point, on l'incorpore dans un script (minimaliste).

#! /usr/bin/env python

import sys

def dico(w):
   with open('liste.de.mots.francais.frgut.txt',encoding='latin1') as f:
       if w+'\n' in f: print ("%s est dans le dictionnaire" % w)
       else: print ("%s n'est pas dans le dictionnaire" % w)


if __name__ == '__main__': # cette clause permet d'utiliser le script comme module, les instructions
    if len(sys.argv) < 2:  # qui suivent ne seront exécutées que si le script est le programme principal
        print ("dic prend au moins un argument")
        sys.exit(1)
    else:
        for w in sys.argv[1:]: dico(w)

Résultat :

[jyt@scriabine M1]$ ./dico.py luke je suis ton père
luke n'est pas dans le dictionnaire
je est dans le dictionnaire
suis est dans le dictionnaire
ton est dans le dictionnaire
père est dans le dictionnaire
In [ ]: