Quel ouvrage constitue correctement le manuel principal de l'examen de certification de base d'ingénieur Python 3 ?
『Pythonチュートリアル』(le Tutoriel Python), publié par O'Reilly Japan
『あたらしいデータ分析の教科書』(Le nouveau manuel d'analyse de données), publié par Shoeisha
『Pythonデータ分析 実践ハンドブック』(Manuel pratique d'analyse de données Python), publié par Impress
『Python実践レシピ』(Recettes pratiques Python), publié par Gijutsu-Hyoronsha
RéponseA. 『Pythonチュートリアル』(le Tutoriel Python), publié par O'Reilly Japan
Le manuel principal de l'examen de base est 『Pythonチュートリアル』(le Tutoriel Python) d'O'Reilly Japan ; la page officielle indique qu'à compter du 1er septembre 2021, l'examen correspond à la 4e édition. Le champ d'examen étant lui aussi publié avec les numéros et titres de chapitre de ce livre, la préparation consiste à maîtriser son contenu selon le poids attribué à chaque chapitre. 『Python実践レシピ』(Recettes pratiques Python) de Gijutsu-Hyoronsha est le manuel de l'examen pratique, 『Pythonによるあたらしいデータ分析の教科書』(Le nouveau manuel d'analyse de données par Python) de Shoeisha celui de l'examen d'analyse de données, et 『Pythonデータ分析 実践ハンドブック』(Manuel pratique d'analyse de données Python) d'Impress celui de l'examen pratique d'analyse de données ; ce sont tous des manuels d'autres examens organisés par la même association. Se tromper de manuel conduit à étudier indéfiniment hors du champ d'examen ; il convient donc de le vérifier en premier lieu.
Q2 | Chapitre le plus fourni
Dans le champ d'examen de l'examen de base, quel chapitre du manuel principal fournit le plus grand nombre de questions ?
Chapitre 5, « Structures de données »
Chapitre 4, « Outils de contrôle du flux »
Chapitre 3, « Une introduction en douceur »
Chapitre 8, « Erreurs et exceptions »
RéponseB. Chapitre 4, « Outils de contrôle du flux »
Le plus fourni est le chapitre 4, « Outils de contrôle du flux », avec 9 questions sur 40. Viennent ensuite le chapitre 5, « Structures de données », avec 7 questions, puis le chapitre 3, « Une introduction en douceur », avec 6 questions, et le chapitre 8, « Erreurs et exceptions », avec 4 questions. Les seuls chapitres 3, 4 et 5 totalisent 22 questions, soit plus de la moitié de l'ensemble. Il est donc rationnel de répartir aussi le temps d'étude en priorité sur ces trois chapitres, et négliger en particulier le chapitre 4, qui traite de la boucle for et de la définition de fonctions, serait irrattrapable.
Q3 | Répartition par chapitre
Dans le champ d'examen de l'examen de base, quelle proportion représente le chapitre 4, « Outils de contrôle du flux » ?
17,5 %
10,0 %
22,5 %
15,0 %
RéponseC. 22,5 %
Le chapitre 4, « Outils de contrôle du flux », représente 9 questions sur 40, soit une proportion de 22,5 %. C'est le chapitre le plus important, suivi par le chapitre 5, « Structures de données », avec 7 questions, soit 17,5 %. 15,0 % correspond aux 6 questions du chapitre 3, « Une introduction en douceur », et 10,0 % correspond aux 4 questions de chacun des chapitres 8, « Erreurs et exceptions », et 10, « Brève excursion dans la bibliothèque standard ». Cette répartition n'est pas un chiffre opérationnel, mais est publiée en tant que champ d'examen lui-même, si bien qu'elle peut servir de base au plan d'étude.
Q4 | Répartition du chapitre 13
Dans le champ d'examen de l'examen de base, combien de questions sont attribuées au chapitre 13, « Et maintenant ? » ?
0 question
1 question
4 questions
2 questions
RéponseA. 0 question
Le chapitre 13, « Et maintenant ? », compte 0 question ; c'est le seul chapitre du champ d'examen qui n'est jamais interrogé. Son contenu guidant vers les prochaines étapes de l'apprentissage, il est exclu du champ d'un examen portant sur la syntaxe. 1 question est attribuée aux chapitres 1, 2, 7, 11, 12 et 14, 2 questions aux chapitres 6 et 9, et 4 questions aux chapitres 8, « Erreurs et exceptions », et 10, « Brève excursion dans la bibliothèque standard ». Tous les chapitres sauf le 13 comptent au moins 1 question ; même les chapitres peu représentés méritent donc au moins un survol du vocabulaire.
Q5 | Le paramètre sep de print
Lors de l'exécution du programme suivant, quelle chaîne s'affiche à l'écran ?
print('Python', 3, 'exam', sep='/')
Python3exam
Python 3 exam
Python/3/exam/
Python/3/exam
RéponseD. Python/3/exam
print() joint les arguments reçus au moyen de l'argument nommé sep. La valeur par défaut de sep est un unique espace ; sans précision, on obtiendrait Python 3 exam, mais ici sep='/' est spécifié, si bien que les éléments sont reliés par des barres obliques pour donner Python/3/exam. Python3exam correspond à sep réglé sur une chaîne vide. Choisir Python/3/exam/, avec un séparateur en fin également, reviendrait à penser que sep est ajouté après chaque élément, alors qu'en réalité il n'apparaît qu'entre les arguments. Ce qui s'ajoute à la fin, c'est end.
Q6 | Le paramètre end de print
En exécutant les 3 lignes suivantes dans l'ordre, qu'affiche l'écran ?
print('A', end='')print('B', end='')print('C')
AB puis C s'affichent sur 2 lignes
ABC s'affiche sur une seule ligne
A B C s'affiche sur une seule ligne
A, puis B, puis C s'affichent sur 3 lignes
RéponseB. ABC s'affiche sur une seule ligne
print() ajoute l'argument nommé end à la fin de la sortie. Sa valeur par défaut est un caractère de saut de ligne, donc sans précision, chaque appel à print() saute une ligne. Ici, les deux premiers appels ont end='', ce qui supprime le saut de ligne, si bien que A et B s'affichent à la suite ; le dernier print() ajoute le saut de ligne par défaut, si bien que ABC s'affiche sur une seule ligne. A B C avec des espaces correspondrait à un seul appel print() recevant trois arguments, 3 lignes correspondrait à l'absence totale de spécification de end, et 2 lignes correspondrait au cas où un seul des end='' aurait été omis.
Q7 | Affichage déballé
Quel est le résultat du programme suivant, qui déballe une liste pour l'afficher ?
nums = [10, 20, 30]print(*nums, sep=', ')
10, 20, 30 s'affiche
102030 s'affiche
[10, 20, 30] s'affiche
10 20 30 s'affiche
RéponseA. 10, 20, 30 s'affiche
Avec un astérisque, print(*nums) transmet chaque élément de la liste comme un argument séparé à print(). Les trois arguments sont donc joints par sep, qui vaut ', ', ce qui donne 10, 20, 30. Sans astérisque, print(nums) transmet la liste comme un seul argument, et l'affichage se fait avec crochets, [10, 20, 30], tel quel. Sans spécifier sep, on obtient l'espace par défaut, 10 20 30, et avec sep='', l'affichage est collé, 102030.
Q8 | Symbole de commentaire
Quelle description des commentaires en Python est correcte ?
Tout ce qui est entouré de /* et */ est ignoré comme commentaire
Tout ce qui suit # jusqu'à la fin de la ligne est ignoré comme commentaire
Tout ce qui suit -- jusqu'à la fin de la ligne est ignoré comme commentaire
Tout ce qui suit // jusqu'à la fin de la ligne est ignoré comme commentaire
RéponseB. Tout ce qui suit # jusqu'à la fin de la ligne est ignoré comme commentaire
Les commentaires en Python s'écrivent avec le symbole dièse, et tout ce qui suit jusqu'à la fin de la ligne est ignoré. Placé en début de ligne, toute la ligne est concernée ; placé au milieu, seule la suite l'est. Il n'existe pas de syntaxe dédiée pour regrouper plusieurs lignes ; il faut donc placer un dièse à chaque ligne. On utilise parfois une chaîne entourée de guillemets triples en guise de commentaire de bloc, mais il s'agit syntaxiquement d'un littéral de chaîne, qui, placé en tête d'une fonction ou d'une classe, est conservé à l'exécution comme docstring. Le double slash est en Python l'opérateur de division entière, et le couple slash-astérisque ou le double tiret sont des notations de commentaire d'autres langages.
Q9 | Indentation
Que se passe-t-il en enregistrant le programme suivant dans un fichier puis en l'exécutant ?
if True: print('one') print('two')
Seul two s'affiche et le traitement se termine
Seul one s'affiche et le traitement se termine
one puis two s'affichent dans cet ordre
Une IndentationError survient et l'exécution s'arrête
RéponseD. Une IndentationError survient et l'exécution s'arrête
Python exprime les blocs par la profondeur de l'indentation, si bien que les instructions appartenant au même bloc doivent avoir la même largeur de retrait. Seule la 3e ligne est plus profonde, et la ligne précédente n'est de plus pas une ligne introduisant un nouveau bloc (une ligne se terminant par deux-points) ; il en résulte une IndentationError: unexpected indent. Cette erreur étant détectée lors de l'analyse syntaxique avant l'exécution, même le print de la 2e ligne ne s'exécute pas, et même one ne s'affiche pas. Si l'indentation manque là où elle est nécessaire, le message est expected an indented block, et si la largeur ne correspond plus en cours de route, c'est unindent does not match any outer indentation level ; mais dans les deux cas, il s'agit d'une IndentationError.
Q10 | Encodage des caractères
Quelle description correcte concerne l'encodage des caractères d'un fichier source Python 3 ?
Shift_JIS est l'encodage par défaut, modifiable par déclaration
UTF-8 est l'encodage par défaut, permettant d'écrire du japonais directement
EUC-JP est l'encodage par défaut, permettant d'écrire du japonais directement
ASCII est l'encodage par défaut, et une déclaration est nécessaire pour inclure du japonais
RéponseB. UTF-8 est l'encodage par défaut, permettant d'écrire du japonais directement
Un fichier source Python 3 est lu par défaut en UTF-8, si bien qu'on peut écrire du japonais directement aussi bien dans les commentaires que dans les littéraux de chaîne. Sous Python 2, l'encodage par défaut était ASCII, et pour inclure du japonais, il fallait écrire une déclaration coding sur la première ou la deuxième ligne du fichier ; sous Python 3, cette déclaration n'est plus nécessaire. On n'écrit une telle déclaration que si l'on souhaite faire lire un fichier enregistré dans un autre encodage qu'UTF-8. Notons qu'il est également possible d'utiliser du japonais dans les identifiants (noms de variables ou de fonctions), bien que cela ne soit pas recommandé du point de vue de la lisibilité.
Q11 | Type de la division
Le programme suivant, traitant une division entre entiers, affiche une valeur en ligne 1 et le nom d'un type en ligne 2. Quelle combinaison obtient-on ?
print(9 / 3)print(type(9 / 3).__name__)
La valeur 3.0, et le type int
La valeur 3.0, et le type float
La valeur 3, et le type int
La valeur 3, et le type float
RéponseB. La valeur 3.0, et le type float
L'opérateur / à barre unique est la division vraie, dont le résultat est toujours un float. Même lorsque la division tombe juste, cela ne fait pas exception : 9 / 3 vaut donc 3.0 et non 3, avec le type float. Penser qu'un calcul entre entiers donne un int mène à choisir 3 et int par erreur ; pour obtenir un int, il faut utiliser la division entière et écrire 9 // 3, qui donne alors 3 et int. Les combinaisons où l'apparence de la valeur et le type ne correspondent pas, comme 3 et float, ou 3.0 et int, ne résultent pas de cette expression.
Q12 | Division entière de nombres négatifs
Quel est le résultat du programme suivant, qui aligne des divisions entières ?
print(9 // 4)print(-9 // 4)
Ligne 1 : 2.0, ligne 2 : -3.0
Ligne 1 : 2, ligne 2 : -3
Ligne 1 : 2.25, ligne 2 : -2.25
Ligne 1 : 2, ligne 2 : -2
RéponseB. Ligne 1 : 2, ligne 2 : -3
L'opérateur // à double barre est la division entière, qui arrondit le quotient vers le bas, c'est-à-dire vers la plus petite valeur sur l'axe numérique. 9 / 4 valant 2,25, 9 // 4 vaut 2 ; -9 / 4 valant -2,25, -9 // 4 vaut non pas -2 mais -3. L'essentiel est que l'arrondi ne se fait pas vers 0 ; choisir -2 reviendrait à penser, comme en langage C, que l'arrondi se fait vers 0. 2,25 et -2,25 sont les valeurs obtenues avec / plutôt que //, et 2,0 et -3,0 correspondent au cas où l'on mélange un float dans les opérandes en écrivant 9.0 // 4 ; si les deux côtés sont des int, le résultat est aussi un int.
Q13 | divmod
Quelle valeur renvoie divmod(-11, 3) ?
(-4, 1)
(-3, -2)
(-4, -2)
(-3, 2)
RéponseA. (-4, 1)
divmod(a, b) renvoie le tuple (a // b, a % b). L'opérateur // de Python arrondissant vers le bas, -11 // 3 vaut -4, et le signe du reste étant aligné sur celui du diviseur, -11 % 3 vaut 1. Le résultat est donc (-4, 1). En raisonnant selon un arrondi vers 0, on obtiendrait un quotient de -3 et un reste de -2, menant à choisir par erreur (-3, -2), mais Python n'adopte pas cette convention. Le quotient et le reste conservent toujours la relation selon laquelle diviseur fois quotient plus reste redonne la valeur d'origine ; on peut donc vérifier : 3 fois -4 plus 1 donne -11. En vérifiant avec cette relation, ni (-3, 2) ni (-4, -2) ne redonnent -11.
Q14 | Troncature de int
Quel est le résultat du programme suivant, qui compare des directions de troncature ?
print(int(-2.7))print(-2.7 // 1)
Ligne 1 : -2, ligne 2 : -2.0
Ligne 1 : -3, ligne 2 : -3.0
Ligne 1 : -2, ligne 2 : -3.0
Ligne 1 : -3, ligne 2 : -2.0
RéponseC. Ligne 1 : -2, ligne 2 : -3.0
La fonction native int() supprime la partie décimale en arrondissant vers 0, si bien que int(-2.7) vaut non pas -3 mais -2. En revanche, // arrondit vers le bas, si bien que -2.7 // 1 va du côté de -3, et comme les opérandes contiennent un float, le résultat est aussi un float, -3.0. Pour les nombres positifs, int(2.7) et 2.7 // 1 vont tous deux du côté de 2, la différence ne se voit donc pas ; c'est avec les nombres négatifs que la direction diverge. Aucun des deux n'est un arrondi classique ; pour arrondir -2.7 à -3, il faut utiliser round(-2.7).
Q15 | Erreur des décimaux
Quel est le résultat du programme suivant, qui affiche deux valeurs booléennes sur 2 lignes ?
float conserve les nombres décimaux en base 2, si bien que des valeurs simples en base 10 comme 0.1 ou 0.7 ne peuvent pas être représentées exactement. En affichant réellement 0.1 + 0.7, on obtient 0.7999999999999999, légèrement différent de 0.8, donc la ligne 1 vaut False. La ligne 2 compare après avoir arrondi avec round() à 2 décimales, si bien que les deux côtés valent 0.8 et le résultat est True. Ce n'est pas un défaut propre à Python mais une propriété de la virgule flottante binaire de la norme IEEE 754 ; c'est pour la même raison que 0.1 + 0.2 donne 0.30000000000000004, ou que 1.1 + 2.2 donne 3.3000000000000003. Il faut éviter les comparaisons d'égalité entre float, et plutôt arrondir au nombre de décimales nécessaire avant de comparer, ou comparer la valeur absolue de la différence à une tolérance, ou encore, pour des cas exigeant une exactitude stricte comme des montants d'argent, utiliser le module decimal.
Q16 | Arrondi de round
Quel est le résultat du programme suivant, qui affiche des valeurs arrondies sur une ligne ?
print(round(1.5), round(2.5), round(3.5))
2 2 4
2 3 4
1 3 3
1 2 3
RéponseA. 2 2 4
La fonction round() de Python arrondit au nombre pair le plus proche, ce qu'on appelle l'arrondi bancaire. Ce n'est que pour une valeur exactement à mi-chemin qu'elle se dirige vers le nombre pair le plus proche : 1.5 devient donc 2, 2.5 reste 2, et 3.5 devient 4, ce qui donne 2 2 4 en sortie. L'arrondi classique enseigné à l'école donnerait 2 3 4, mais Python n'adopte pas cette convention. 1 2 3 correspond à une simple troncature de la partie décimale, et 1 3 3 correspond à un arrondi systématique vers le nombre impair ; ni l'un ni l'autre ne correspond au comportement réel. Notons que round() sans second argument renvoie un int, tandis qu'en précisant le nombre de décimales, comme round(2.5, 0), un float, 2.0, est renvoyé.
Q17 | bool est un int
Quel est le résultat du programme suivant, qui traite des valeurs booléennes comme des nombres ?
print(True + True)print(isinstance(True, int))
Ligne 1 : True, ligne 2 : True
Ligne 1 : 2, ligne 2 : False
Ligne 1 : 2, ligne 2 : True
Ligne 1 : True, ligne 2 : False
RéponseC. Ligne 1 : 2, ligne 2 : True
bool étant un type héritant de int, True peut être utilisé directement dans un calcul numérique comme l'entier 1, et False comme l'entier 0. True + True donne 1 plus 1, soit 2, et isinstance(True, int) renvoie True. Penser que la ligne 1 vaut True reviendrait à confondre + avec le OU logique, alors que le OU logique de Python est or, et True or True donnerait True. issubclass(bool, int) vaut également True, et sum([True, False, True]) vaut 2 pour la même raison. Cette propriété est souvent utilisée pour compter le nombre d'éléments satisfaisant une condition.
Q18 | Précision des entiers
Quelle description du type int de Python 3 est correcte ?
Il n'a pas de limite du nombre de chiffres et peut traiter des valeurs aussi grandes que la mémoire le permet
Au-delà de 32 bits, une valeur peut déborder et devenir négative
Une OverflowError est levée dès que le nombre de chiffres dépasse une limite
Au-delà de 64 bits, il est automatiquement converti en float pour le calcul
RéponseA. Il n'a pas de limite du nombre de chiffres et peut traiter des valeurs aussi grandes que la mémoire le permet
Le type int de Python 3 est de précision arbitraire, sans limite de nombre de chiffres. 3 ** 40 se calcule exactement comme 12157665459056928801, ce qui dépasse la plage d'un entier signé sur 64 bits, mais le type reste int. Des valeurs comme 2 ** 1000 sont également traitées, et en comptant le nombre de chiffres avec len(str(2 ** 1000)), on obtient 302 chiffres. N'étant pas un entier de longueur fixe comme en langage C, il ne déborde jamais vers une valeur négative, ni ne bascule automatiquement vers float. Une OverflowError survient par exemple lorsqu'une valeur dépasse la plage représentable par un float, mais ne survient pas simplement parce que le nombre de chiffres d'un int augmente. Cependant, le temps de calcul et la mémoire augmentent à mesure que le nombre de chiffres croît.
Q19 | Indexation de bytes
Dans le programme suivant, traitant une séquence d'octets, quels sont les résultats des lignes 2 et 3 ?
b = 'abc'.encode()print(b[0])print(b[0:1])
Ligne 1 : b'a', ligne 2 : b'a'
Ligne 1 : 97, ligne 2 : b'a'
Ligne 1 : 97, ligne 2 : 97
Ligne 1 : a, ligne 2 : b'a'
RéponseB. Ligne 1 : 97, ligne 2 : b'a'
Accéder à bytes avec un indice entier renvoie la valeur de l'octet à cette position sous forme d'int. Le premier octet de b'abc', l'encodage UTF-8 de 'abc', est le point de code de 'a', soit 97. En revanche, extraire par découpage (slice) renvoie un bytes de longueur 1, donc b[0:1] vaut b'a'. Avec str, s[0] comme s[0:1] donnent le même str 'a', ce qui contraste avec le comportement de bytes. L'affichage sous forme de b'a' plutôt que a s'explique par le fait que print() affiche bytes sous sa forme repr ; pour revenir à une chaîne, on utilise b.decode().
Q20 | Base et caractère
Quel est le résultat du programme suivant, qui aligne des conversions de base et de code de caractère ?
Le second argument de int() étant la base, int('1010', 2) lit la chaîne comme un nombre binaire et renvoie 10. Penser que le résultat reste 1010 correspondrait à avoir négligé cette base. bin() renvoie une chaîne préfixée par 0b, soit '0b1010', et hex() renvoie une chaîne en minuscules préfixée par 0x, soit '0xff'. Le résultat n'est jamais en majuscules 0xFF ; pour obtenir une notation en majuscules, on utilise format(255, 'X'). ord() renvoie le point de code d'un caractère, et pour la majuscule A, il vaut 65. 97 est le point de code de la minuscule a ; la conversion inverse s'écrit chr(65) et redonne 'A'.
Q21 | Découpage (slicing)
Quel est le résultat du programme suivant, qui traite un découpage (slice) de chaîne ?
s = 'Pythonic'print(s[2:5])print(s[-3:])
Ligne 1 : tho, ligne 2 : nic
Ligne 1 : tho, ligne 2 : ic
Ligne 1 : thon, ligne 2 : nic
Ligne 1 : yth, ligne 2 : nic
RéponseA. Ligne 1 : tho, ligne 2 : nic
s[2:5] extrait à partir de la position d'indice 2 jusqu'à juste avant l'indice 5. L'indice 2 de 'Pythonic' étant t, on obtient les 3 caractères t, h, o, soit tho. La position de fin n'étant pas incluse, on n'obtient pas thon. En comptant les indices à partir de 1 et en lisant « à partir du 2e caractère », on choisirait par erreur yth, qui correspond à s[1:4]. s[-3:] utilise un indice négatif, donc compte depuis la fin, et renvoie à partir du 3e caractère depuis la fin, n, jusqu'à la fin, soit nic. En lisant à tort -3 comme « jusqu'au 3e caractère depuis la fin », on choisirait ic, qui correspond à s[-2:]. Retenir que l'indexation commence à 0 et qu'un indice négatif compte la fin comme -1 évite toute confusion.
Q22 | Hors limites et in
Quel est le résultat du programme suivant, qui affiche deux résultats de test ?
s = 'Python'print(s[100:200] == '')print('py' in s)
Ligne 1 : True, ligne 2 : False
Ligne 1 : True, ligne 2 : True
Ligne 1 : False, ligne 2 : True
Ligne 1 : False, ligne 2 : False
RéponseA. Ligne 1 : True, ligne 2 : False
Un découpage (slice) ne lève pas d'exception même si la plage dépasse la longueur de la chaîne ; il ne renvoie que la partie qui se recouvre. 'Python' ne comptant que 6 caractères, s[100:200] vaut donc une chaîne vide, et la comparaison avec une chaîne vide donne True. Un indice unique s[100], en revanche, lèverait une IndexError ; c'est là le contraste. À la ligne 2, l'opérateur in vérifie la présence d'une sous-chaîne, mais en respectant la casse, si bien que la minuscule 'py' n'est pas contenue dans 'Python' et donne False. Avec 'Py' ou 'th', le résultat serait True.
Q23 | Les chaînes sont immuables
Que se passe-t-il en écrivant le programme suivant dans un fichier puis en l'exécutant ?
s = 'abc's[0] = 'z'print(s)
Une TypeError survient et l'affectation échoue
Il s'affiche en ayant été remplacé par zbc
Une IndexError survient et l'affectation échoue
Il s'affiche inchangé, abc
RéponseA. Une TypeError survient et l'affectation échoue
str étant immuable, c'est-à-dire que son contenu ne peut pas être modifié après création, il n'est pas possible de réécrire un seul caractère par indexation. s[0] = 'z' provoque une TypeError: 'str' object does not support item assignment, ce qui arrête l'exécution ; le print ne s'exécute donc pas non plus. IndexError survient lorsque l'indice est hors de la plage, ce qui n'est pas le cas ici puisque 0 est un indice valide ; c'est donc un autre sujet. Pour modifier le contenu, il faut créer une nouvelle chaîne et la réassembler, par exemple s = 'z' + s[1:]. Une liste étant mutable, on peut en revanche réécrire un élément avec la même syntaxe.
Q24 | Retour d'une méthode
Quel est le résultat du programme suivant, qui appelle des méthodes de chaîne ?
s = 'exam's.upper()print(s)print(s.replace('e', 'E'))
Ligne 1 : EXAM, ligne 2 : Exam
Ligne 1 : EXAM, ligne 2 : EXAM
Ligne 1 : exam, ligne 2 : exam
Ligne 1 : exam, ligne 2 : Exam
RéponseD. Ligne 1 : exam, ligne 2 : Exam
Les méthodes de chaîne ne modifient pas la chaîne d'origine ; elles créent et renvoient une nouvelle chaîne. À la ligne 2, s.upper() crée 'EXAM', mais comme la valeur n'est affectée nulle part, elle est simplement perdue, et s reste 'exam'. print(s) affiche donc exam. La ligne 4 affiche directement la valeur de retour de s.replace('e', 'E'), donnant Exam, mais cela non plus ne modifie pas s lui-même. Pour conserver le résultat, il faut réaffecter, comme dans s = s.upper(). Cela contraste avec des méthodes comme sort() sur une liste, qui trient sur place et renvoient None.
Q25 | f-string
Quel est le résultat du programme suivant, qui affiche des valeurs avec un formatage spécifié ?
n = 2.71828print(f'{n:.2f}')print(f'{"ok"!r}')
Ligne 1 : 2.71, ligne 2 : 'ok'
Ligne 1 : 2.72, ligne 2 : ok
Ligne 1 : 2.718, ligne 2 : ok
Ligne 1 : 2.72, ligne 2 : 'ok'
RéponseD. Ligne 1 : 2.72, ligne 2 : 'ok'
La spécification de format :.2f d'une f-string arrondit à 2 décimales pour l'affichage, si bien que 2.71828 devient 2.72. Il ne s'agit pas d'une troncature, donc on n'obtient pas 2.71 ; 2.718 correspondrait à l'écriture :.3f. Le !r de la ligne 2 est une spécification de conversion, affichant la valeur sous la forme de repr(). Appliqué à une chaîne, il ajoute des guillemets, donnant 'ok' ; sans !r, on obtiendrait simplement ok. La syntaxe de formatage étant commune avec str.format(), écrire '{n:.2f}'.format(n=2.71828) donne le même résultat, 2.72.
Q26 | split
Quel est le résultat du programme suivant, qui découpe une chaîne ?
print('a b c'.split())print('a,b,c'.split(',', 1))
['a', 'b', 'c'] puis ['a', 'b', 'c']
['a', 'b', '', 'c'] puis ['a', 'b,c']
['a', 'b', 'c'] puis ['a', 'b,c']
['a', 'b', '', 'c'] puis ['a', 'b', 'c']
RéponseC. ['a', 'b', 'c'] puis ['a', 'b,c']
En appelant split() sans argument, les espaces consécutifs sont traités comme un seul séparateur, sans créer d'élément vide. 'a b c'.split() donne donc les 3 éléments ['a', 'b', 'c']. En précisant explicitement le séparateur avec 'a b c'.split(' '), la coupe se fait à chaque espace un par un, laissant une chaîne vide et donnant les 4 éléments ['a', 'b', '', 'c']. Le second argument, maxsplit, limite le nombre de coupes ; en passant 1, une seule coupe est faite au premier séparateur, donnant ['a', 'b,c'], le reste restant regroupé sans être coupé. En omettant cet argument, tout est coupé, donnant ['a', 'b', 'c'].
Q27 | strip
Quel est le résultat du programme suivant, qui retire des caractères des deux extrémités ?
L'argument de strip() est « l'ensemble des caractères à retirer » : depuis les deux extrémités, on continue de retirer tant que le caractère appartient à cet ensemble. Ce n'est pas la suppression d'une seule occurrence de la sous-chaîne 'x' ; 'xxabxx'.strip('x') retire donc tous les x des deux côtés, donnant ab. Penser qu'un seul caractère est retiré à chaque extrémité conduirait à choisir xabx par erreur. lstrip() ne traite que le côté gauche, donnant abxx, et rstrip() ne traite que le côté droit, donnant xxab. Sans argument, ce sont les espaces qui sont retirés. Étant traité comme un ensemble, écrire 'xxabxx'.strip('xa') retire aussi le xx à gauche et le a suivant, ne laissant que b.
Q28 | join et répétition
Quel est le résultat du programme suivant, qui relie des chaînes ?
print('-'.join('abc'))print('ab' * 3)
Ligne 1 : -a-b-c-, ligne 2 : ababab
Ligne 1 : abc, ligne 2 : ababab
Ligne 1 : a-b-c, ligne 2 : ab ab ab
Ligne 1 : a-b-c, ligne 2 : ababab
RéponseD. Ligne 1 : a-b-c, ligne 2 : ababab
join() relie chaque élément de l'itérable transmis en utilisant la chaîne appelante comme séparateur. Une chaîne étant elle-même un itérable dont on peut extraire les caractères un par un, '-'.join('abc') relie 'a', 'b' et 'c' par des tirets, donnant a-b-c. Le séparateur ne s'insérant qu'entre les éléments, il n'apparaît ni au début ni à la fin, donc pas de -a-b-c-. On obtiendrait abc sans séparateur en écrivant ''.join('abc'). L'opérateur * répète une chaîne un nombre de fois donné, donc 'ab' * 3 donne ababab, sans espace entre les répétitions. Pour obtenir ab ab ab, il faudrait écrire ' '.join(['ab'] * 3).
Q29 | find et index
Quel est le résultat du programme suivant, qui recherche une sous-chaîne ?
find() renvoie -1 lorsque la sous-chaîne n'est pas trouvée, sans lever d'exception. 'banana' ne contenant pas 'z', le résultat est -1. 0 correspond au cas où l'élément est trouvé au tout début ; il ne faut pas le confondre avec le cas où il n'est pas trouvé. index() renvoie, comme find(), la position trouvée : la première apparition de 'n' dans 'banana' se situe à l'indice 2, donc le résultat est 2. 3 correspondrait à compter les indices à partir de 1 en lisant « le 3e caractère », et 4 est la dernière position d'apparition, qu'on obtiendrait avec rfind() ou rindex(). La seule différence entre les deux méthodes concerne le cas où rien n'est trouvé : index() lève alors une ValueError: substring not found et arrête le traitement.
Q30 | Chaîne brute (raw)
Quel est le résultat du programme suivant, qui compte des caractères ?
print(len(r'a\nb'), len('a\nb'))
3 4
4 4
3 3
4 3
RéponseD. 4 3
Dans une chaîne brute (raw), préfixée par r, une barre oblique inverse n'est pas interprétée comme le début d'une séquence d'échappement. r'a\nb' compte donc les 4 caractères a, barre oblique inverse, n, b, si bien que len vaut 4. En revanche, dans la chaîne normale 'a\nb', \n est remplacé par un unique caractère de saut de ligne, donnant les 3 caractères a, saut de ligne, b, avec len valant 3. Compter les deux comme des séquences d'échappement donnerait 3 3, et les compter tous les deux comme des caractères bruts donnerait 4 4, mais le point essentiel est que le traitement change selon la présence ou non du r. Même avec r, le type reste un str ordinaire, et ne devient pas un type spécial. Notons que len('\\') vaut 1, les deux barres obliques inverses étant doublées pour en écrire une seule.
Entraînement : répondez aux questions de cette page
Cet outil d'entraînement pose les questions dans un ordre aléatoire (il fonctionne lorsque JavaScript est activé). Vous pouvez de toute façon lire toutes les questions et explications ci-dessus.
* Les explications sont fournies à titre d'information pour l'étude. Le programme et le système des examens changent selon les années : vérifiez toujours les annonces officielles de l'organisme qui organise l'examen.
Cette page est une traduction du texte original japonais. En cas de différence entre la traduction et l'original, la version japonaise fait foi. Voir l'original en japonais