Enseignant principal (CMs, ...) : Sébastien HOARAU (seb.hoarau@...)
Chargé de TDs pour les groupes IEEA_1+3+5 et SF3-1b
: Philippe MARTIN (philippe.martin@...)
Cette page ( http://www.phmartin.info/cours/python/ )
rappelle certaines informations (liens, ...) importantes pour les TDs.
* Page centrale du cours sur Moodle (CMs, TDs, solutions, forum, ...).
* MOOC "Apprendre à coder avec Python" (exo UpyLaB 2.1) ;
* Page Web du MOOC relative au livre du cours :
c'est la page "Aide mémoire" qui est principalement
affichée (ayez la toujours ouverte, elle vous sera utile) mais
une page "Bonnes pratiques" est aussi
directement accessible et, via un onglet, le "Manuel du cours" l'est aussi ;
si vous avez des difficultés à
trouver un exercice particulier dans le MOOC, faites une recherche (<ctrl>-F)
dans ce manuel.
* Documentations officielles sur Python 3.6.3.
Voici ci-dessous des aides/rappels complémentaires à celles
listées dans
la page de "Bonnes pratiques" référée ci-dessus.
Plus vous suivrez de "bonnes pratiques",
plus votre code sera lisible/compréhensible (par vous et d'autres), réutilisable
et
automatiquement analysable/modifiable, et donc
1. plus vous éviterez des erreurs et gagnerez du temps,
2. plus vous montrerez que vous savez suivre des spécifications, ce qui est fondamental
dans
le développement de logiciels (voyez ces
amusantes illustrations et notez que généralement
au moins
70% de la valeur d'un code tient dans sa maintenabiité/réutilisabilité),
et donc
3. plus favorable sera – ou aura tendance à être –
l'évaluation de votre chargé de TDs.
Parcours d'une collection (tuple, array, ...) via une boucle "for" :
- via les indices :
for i in range(len(collection)): element= collection[i]
utilisez i, i1, i2, ... pour (le nom de la variable contenant) l'indice courant
- directement : for element in collection: ...
remplacez element et collection par
des termes appropriés, e.g., respectivement, w et words (ou arrWord),
a et args (ou arrArg), c et str, n et arrInteger, ...
Autrement, évitez les abbréviations.
Conventions (/ bonnes pratiques) lexicales pour les noms de variables :
(à utiliser au minimum pour les exercises que vous voulez faire évaluer par
votre tuteur ;
les exemples de fonctions donnés ci-dessous illustrent ces
conventions)
Type | Préfixes utilisables |
---|---|
Any(thing) | "x", "element","elem","e", "arg", "dest","d" |
Object | "obj","o" |
Collection | "coll" |
List (→ un-indexed) | "list","lst","lis","li" (les "listes" de Python sont en fait indexés !) |
Array (→ indexed coll.) | "a","arr", "table" (→ à utiliser pour les "listes" de Python) |
Pair | "pair" |
String (of chars) | "s","str", "name","id", "word","w", "text" |
AssociativeArray | "aa", "dict" |
Function | "fct" |
File | "file" |
Value | "v","val","value |
Boolean | "b","has","is","are","no","do","does",with" |
Char | "c" |
Number | "num" |
Real (float, ...) | "r" |
Integer (can be < -1) | "zi","int" |
Integer >= -1 | "i","index" |
Natural | "n","nb","lng","depth" |
Conventions lexicales pour les noms de fonctions : le style
simili-orienté-objet (i.e.
<TypeOfTheFirstParameter>_<NameForWhatTheFctDoesOnObjectsOfThisType>)
si vous ne savez pas ce qu'est le style orienté-objet ou si vous ne l'utilisez pas,
e.g. Integer_isGreaterThan, String_isInUppercase, String_firstWord,
String_betweenMarkers, SequenceOfIntegers_maxMinusMin,
String_mostFrequentWord
(cf. exemples de fonctions ci-dessous).
Note : le MOOC imposant des noms de fonctions pour pouvoir effectuer des tests,
vous devez les utiliser. Néanmoins, vous êtes invités à utilisez un
commentaire après les paramètres (sur la même ligne si possible) pour
indiquer un nom plus explicite afin de
i) vous guider/aider dans la réalisation de votre fonction, et
ii) aider votre lecteur et aider à vous évaluer.
"prepend" : "ajouter au début de".
"append" : "ajouter à la fin de".
E.g. "append the string 'abc' to the string 'def' ": "ajouter la
chaîne de
caractères 'abc' à la fin de la
chaîne de caractères 'def' "
(→ "concaténer ces deux chaînes").
Note : "prepend", "append" and "extend" modifient des chaînes de caractères.
Une fonction ne doit pas modifier ses paramètres (collections/objets)
(sauf s'il cela est explicitement demandé) ni les dupliquer (lorsque c'est possible ;
pour vos exercices, c'est possible).
Ne dupliquez pas des lignes de code à divers endroits : encapsulez les dans une
fonction et appelez la.
N'appelez pas `len(text)' dans une boucle : initialisez
une variable à `len(text)' avant la boucle puis
utilisez la dans la boucle.
Une fonction ne doit pas parcourir une collection plusieurs fois (via une boucle ou
des appels de fonctions) lorsqu'elle peut ne la parcourir qu'une fois.
Donc, lorsque possible (et pour vos exercices, ce le sera), dans une boucle qui
parcoure
une collection, celle-ci ne doit pas aussi être parcouru via
l'operateur "in" ou une fonction comme
find, search or index.
N'utilisez pas de fonctions plus génériques que la fonction que l'on vous
a demandé d'écrire
(puisqu'on vous a demandé de l'écrire
pour que vous compreniez comment marche une telle fonction :
appeler une fonction qui
fait le travail à votre place ne vous fera pas apprendre).
Donc, pour vos exercices, n'utilisez pas les fonctions de la bibiothèque
de Python telles que
find, search, index, replace, split, join, enumerate, endswith,
count, max, min, ... (+ les intervals, parfois)
sans l'accord de votre tuteur.
Pour votre projet,
vous pouvez utiliser
ces fonctions, inutile de demander.
Lorsque vous ne savez pas comment écrire une étape E de votre fonction :
utilisez un commentaire en anglais décrivant (ce qui doit être fait dans) E
– ou appelez une fonction fE qui implémente E –
puis traduisez en python votre commentaire ou écrivez votre fonction fE
(si vous êtes bloqué sur ce dernier point, relisez votre cours ou cherchez
les fonctions adéquates sur le Web)
Nombre variable de paramètres :
def fct (str,*args): for a in args: ...
Avec cette définition, l'appel fct("str",1,2,3)
est équivalent à fct("str",(1,2,3))
sans le *
dans la définition ci-dessus.
Exemple de spécification de valeur par défault pour des paramètres :
def fct (str= "Hello", n= 0): ...
Exemple de fonctions ou conseils relatifs à l'usage de Checkio :
Évitez Internet Explorer (qui a quelques problèmes ;
utilisez plutôt Firefox ou Chrome).
Pour l'exercice "First Word" (de Elementary, dans Checkio),
ici renommé String_firstWord,
notez qu'un "mot" ["word"] est
- une suite de caractères qui ne sont pas des caractères
de punctuation, et donc
- précédé et/ou suivi par rien ou par des
caractères de punctuation.
Implémentant cette définition, voici au moins 90% de cette fonction :
def String_firstWord (text: str) -> str: #this function uses a string (text) and returns a string (w) w= "" # initialize w to the empty string sPunctuations= ( ... ) # initialize sPunctuations (a list; "...": to complete) lng= len(text) # initialize lng since it is used more than once below for i1 in range(0,lng): # skip the punctuations before the 1st word (in text) c= text[i1] # c is the current character if (c not in sPunctuations): # if c is not a sPunctuations break # exit loop (c is the 1st character of the 1st word) for i2 in range(i1,lng): # starting from i1, skip the non-punctuations and c= text[i2] # build w (append the characters to w) if (c in sPunctuations): # if c is a punctuation character ... # do something (you have to write this part) else: w+= ... # else append c to w return w # return w (which now has all the characters of the 1st word)
Pour que l'exercise "Between Markers" soit instructif,
n'utilisez pas la fonction
index() ou une autre fonction qui fait l'essentiel du travail.
Voici ci-dessous au moins 75% de cette fonction. Notez les similarités avec
le
code de first_word() ci-dessus. "w+= ..." aurait pu être utilisé comme ci-dessus
mais, pour changer, "return text[iEndOfStrStart : ...]" est utilisé.
def String_betweenMarkers (text:str, strStart:str, strEnd:str) -> str: #if strStart is not in text, the beginning of text is the begining of the string to return #if strEnd is not in text, the end of text is the end of the string to return #if strEnd occurs before strStart in text, an empty string is returned lng= len(text) lngStrStart= len(strStart) #since len(strStart) is needed in the loop below lngStrEnd= len(strEnd) #idem iEndOfStrStart= 0 #index of the end of strStart in text iStrEnd= ... #index of strEnd in text print("==============================") #trace for clarity purposes for i1 in range(0,lng): #loop from 0 to the last index of text #print(f"1. i1:{i1}",text[i1]) # trace for debugging purposes for j in range(lngStrStart): # loop to test if there is a strStart at text+i1 #print(f" 1. text[{i1}+{j}]:{text[i1+j]} strStart[{j}]:{strStart[j]}") if text[i1+j] != strStart[j]: break # stop as soon as it is clear this is not the case else: print(" no break") #print(f" 1. j:{j} lngStrStart:{lngStrStart}") print(f" 1. text[{i1}+{j}]:{text[i1+j]} strStart[{lngStrStart-1}]:{strStart[lngStrStart-1]}") if (j==lngStrStart-1) and (text[i1+j]==strStart[lngStrStart-1]): #if strStart is at text+i1 iEndOfStrStart= i1 + lngStrStart # re-initialize iEndOfStrStart print("1. iEndOfStrStart:",iEndOfStrStart) break # stop searching print("------------------------------") #trace for clarity purposes for i2 in range(...,lng): #loop from ... (not exactly i1) to the last index of text for j in range(lngStrEnd): # loop to test if there is an strEnd at text+i2 if ... # ... if (j==lngStrEnd-1) and ... : # if there is an strEnd at text+i2 iStrEnd= ... # ... if iStrEnd < iEndOfStrStart: ... # ... (reason for "... (not exactly i1)" above) ... # ... return text[iEndOfStrStart : ...] #return the text between iEndOfStrStart and ...
Pour l'exercice "Number Base", il est très facile
d'utiliser fonction int() (→ peu de points)
et plus dur&formateur de ne pas l'utiliser : pour cela, vous pouvez par exemple
utiliser
l'un des algorithmes ici pointés.
Comme exemple de fonction calculant un maximum/minimum,
sans utiliser max()/min(),
voici le code de la fonction "The Most Numbers"
(ici renommée SequenceOfIntegers_maxMinusMin).
Cette fonction calcule le maximum moins le minimum de ses arguments
(ce sont des entiers).
Le code étant ici donné, vous n'aurez aucun point pour
l'implémentation de cette fonction dans Checkio.
from typing import Sequence, TypeVar def SequenceOfIntegers_maxMinusMin (*args : Sequence[int]) -> int: intMin= 100; intMax= -100 #precondition: for each a in args, we have -100 < a < 100 if (len(args) == 0): return 0 for a in args: if (a < intMin): intMin= a elif(a > intMax): intMax= a return intMax - intMin
Pour l'exercice "Most Frequent", commencez par regarder comment
utiliser les "dictionnaires" (associative arrays)
en Python
(cf. votre cours ; mots clés pour Google: "dictionnary" ou "associative array").
def String_mostFrequentWord (sWords: str) -> int: aaFrequency= {}; for w in sWords: aaFrequency[w]= 0 #initialize/reset the associative array aaFrequency for w in sWords: ... #initialize/update aaFrequency with the frequencies of the words nMax= 0; wordWithNMax= "" for w in aaFrequency: #or: for w in aaFrequency.keys(): n= aaFrequency[w] #frequency of w if n > ...: # nMax= ... # wordWithNMax= ... # return wordWithNMax