<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<question type="category">
  <category>
    <text>$course$/QCM de NSI/Première/Dictionnaires</text>
  </category>
  <info format="html">
    <text><![CDATA[<p>Type construit dict en Python : association<br/>
clé-valeur, création, accès, parcours, méthodes<br/>
keys, values et items, test in. Comparaison<br/>
avec les listes, applications classiques (comptage,<br/>
indexation), implémentation par table de hachage.</p>]]></text>
  </info>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q01 : Notion de dictionnaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'est-ce qu'un <strong>dictionnaire</strong> Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'implémentation interne d'un<br/>
dictionnaire repose sur une table<br/>
de hachage. L'accès à une valeur<br/>
par sa clé est en moyenne en<br/>
O(1). Depuis Python 3.7,<br/>
l'ordre d'insertion des paires<br/>
est conservé.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un fichier au format CSV chargé en mémoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un fichier CSV est un format de<br/>
stockage de données tabulaires,<br/>
alors qu'un dictionnaire est<br/>
une structure de données interne<br/>
au programme. On peut<br/>
néanmoins construire un<br/>
dictionnaire à partir d'un<br/>
fichier CSV.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une liste dont les indices sont des entiers consécutifs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette description correspond<br/>
précisément à une <strong>liste</strong>, et<br/>
non à un dictionnaire. Une liste<br/>
est indexée par des positions<br/>
entières ; un dictionnaire est<br/>
indexé par des clés<br/>
quelconques.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une structure qui associe des clés à des valeurs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : l'accès à une valeur se<br/>
fait directement par sa clé, rapidement.<br/>
On peut le voir comme un index<br/>
ou un annuaire. Un dictionnaire<br/>
est aussi appelé « tableau<br/>
associatif » dans certains<br/>
langages.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une chaîne de caractères ordonnée, indexée par position</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Une chaîne de caractères est<br/>
une séquence ordonnée de<br/>
caractères, alors qu'un<br/>
dictionnaire est une<br/>
structure associative.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q02 : Création</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment crée-t-on un dictionnaire<br/>
vide en Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour créer un dictionnaire avec<br/>
des valeurs initiales :<br/>
d = {"alice": 17, "bob": 16}.<br/>
Les paires sont séparées par des<br/>
virgules, et chaque paire est<br/>
formée d'une clé et d'une valeur<br/>
séparées par deux-points.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec la syntaxe d = ()</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette syntaxe crée un <strong>tuple</strong><br/>
vide, et non un dictionnaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec la syntaxe d = []</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette syntaxe crée une <strong>liste</strong><br/>
vide, et non un dictionnaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Avec la syntaxe d = {}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On utilise des accolades. Une<br/>
forme alternative consiste à<br/>
écrire d = dict().</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec la syntaxe d = dict[]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette syntaxe n'est pas valide<br/>
en Python.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q03 : Accès par clé</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment accède-t-on à la <strong>valeur</strong><br/>
associée à la clé "nom" dans le<br/>
dictionnaire d = {"nom": "Alice"} ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour éviter une KeyError, on<br/>
teste d'abord la présence de la<br/>
clé avec if "nom" in d: avant<br/>
de lire d["nom"]. Le test<br/>
"age" in d vaut False si le<br/>
dictionnaire n'a pas de clé<br/>
"age".</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d(nom)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les parenthèses correspondent<br/>
à un appel de fonction, pas à<br/>
un accès dans un<br/>
dictionnaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d.nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette syntaxe est utilisée pour<br/>
accéder aux attributs d'un<br/>
objet, et non aux clés d'un<br/>
dictionnaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Avec d["nom"]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On utilise les crochets, en<br/>
plaçant la clé entre<br/>
guillemets s'il s'agit d'une<br/>
chaîne. Si la clé n'existe<br/>
pas, Python lève une<br/>
exception KeyError.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d-&gt;nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette syntaxe est utilisée en<br/>
C ou en PHP, mais pas en<br/>
Python.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q04 : Ajouter une entrée</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment ajoute-t-on la paire<br/>
"age": 17 à un dictionnaire d<br/>
en Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La même syntaxe permet à la fois<br/>
la création d'une nouvelle<br/>
entrée et la mise à jour d'une<br/>
entrée existante. On ne fait<br/>
pas de distinction syntaxique<br/>
entre l'ajout et la<br/>
modification.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d.append("age", 17)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La méthode append n'existe<br/>
pas pour les dictionnaires.<br/>
Elle est définie pour les<br/>
listes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d.put("age", 17)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette syntaxe est utilisée en<br/>
Java ou en Go, mais pas en<br/>
Python.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d.add("age": 17)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La méthode add n'existe pas<br/>
pour les dictionnaires ; elle<br/>
appartient aux ensembles, un<br/>
autre type de collection qui<br/>
n'est pas au programme de<br/>
première.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Avec d["age"] = 17</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Si la clé n'existe pas, elle<br/>
est créée. Si elle existait<br/>
déjà, sa valeur est tout<br/>
simplement mise à jour.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q05 : Longueur d'un dictionnaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment connaître le <strong>nombre de paires</strong> clé-valeur d'un<br/>
dictionnaire ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'égalité len(d) == 0 revient<br/>
à dire que le dictionnaire est<br/>
vide. Comme pour les listes, le<br/>
test if d: est plus<br/>
idiomatique en Python : il est<br/>
vrai si et seulement si le<br/>
dictionnaire n'est pas vide.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d.length</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>L'attribut length n'existe<br/>
pas pour les dictionnaires<br/>
en Python.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Avec len(d)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La fonction native len<br/>
fonctionne sur les<br/>
dictionnaires comme sur<br/>
d'autres conteneurs (listes,<br/>
chaînes, ensembles, tuples).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d.size()</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La méthode size n'existe<br/>
pas pour les dictionnaires<br/>
en Python.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec count(d)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La fonction count n'est pas<br/>
définie sur les<br/>
dictionnaires.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q06 : Parcourir un dictionnaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que parcourt par défaut la boucle<br/>
for x in d:, où d est un<br/>
dictionnaire ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Un idiome très courant :</p>
<p>`<code>python<br/>
for cle, valeur in d.items():<br/>
    print(cle, valeur)<br/>
</code>`</p>
<p>Cette construction est très<br/>
pratique pour parcourir un<br/>
dictionnaire tout en conservant<br/>
l'association entre clé et<br/>
valeur.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les paires clé-valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pour parcourir les paires<br/>
clé-valeur, il faut<br/>
explicitement écrire<br/>
for k, v in d.items():.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les clés du dictionnaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette boucle est équivalente à<br/>
for x in d.keys():. Pour<br/>
parcourir les valeurs, on<br/>
écrit for v in d.values():.<br/>
Pour parcourir les paires<br/>
clé-valeur, on utilise<br/>
for k, v in d.items():.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les valeurs du dictionnaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Par défaut, la boucle parcourt<br/>
les <strong>clés</strong> du dictionnaire,<br/>
et non ses valeurs. Pour<br/>
accéder aux valeurs, on<br/>
utilise d.values().</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les indices du dictionnaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un dictionnaire n'a pas<br/>
d'indices entiers comme une<br/>
liste. Il a uniquement des<br/>
clés, qui peuvent être de<br/>
types variés.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q07 : Tester la présence d'une clé</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment teste-t-on si la clé<br/>
"nom" existe dans le<br/>
dictionnaire d ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour tester la présence parmi<br/>
les <strong>valeurs</strong>, on écrit<br/>
valeur in d.values(). Cette<br/>
opération est en moyenne en<br/>
O(n), donc plus coûteuse que<br/>
la recherche d'une clé.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d["nom"]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette syntaxe accède<br/>
directement à la valeur<br/>
associée à la clé. Elle<br/>
provoque une exception<br/>
KeyError si la clé est<br/>
absente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d.has("nom")</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La méthode has n'existe pas<br/>
en Python 3. Une méthode<br/>
has_key existait en Python<br/>
2, mais elle a été supprimée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec d.contains("nom")</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La méthode contains n'existe<br/>
pas pour les dictionnaires en<br/>
Python.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Avec "nom" in d</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>L'opérateur in testé sur un<br/>
dictionnaire vérifie la<br/>
présence parmi les <strong>clés</strong>.<br/>
Cette opération est en<br/>
O(1) en moyenne.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q08 : Méthode keys</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Soit d = {"a": 1, "b": 2}. Que vaut<br/>
list(d.keys()) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Trois vues sur un dictionnaire : keys() (les<br/>
clés), values() (les valeurs) et items() (les<br/>
couples). Parcourir directement d revient à<br/>
parcourir d.keys().</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[1, 2]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce sont les <strong>valeurs</strong>, que renvoie<br/>
d.values(). La méthode keys ne fournit que<br/>
les clés.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>['a', 'b']</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : d.keys() fournit les clés du<br/>
dictionnaire, dans l'ordre d'insertion, et<br/>
list(...) les range dans une liste. C'est<br/>
aussi ce que parcourt for k in d:.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[('a', 1), ('b', 2)]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les couples (clé, valeur) sont<br/>
fournis par d.items(), pas par keys.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>['a', 1, 'b', 2]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : clés et valeurs ne sont jamais<br/>
mélangées dans une même liste. keys ne<br/>
renvoie que les clés, values que les valeurs.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q09 : Cas d'usage typique</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lequel des cas suivants est un<br/>
usage <strong>typique</strong> d'un<br/>
dictionnaire ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Quelques cas d'usage classiques :<br/>
indexation (mot vers<br/>
définition), comptage (mot vers<br/>
nombre d'occurrences),<br/>
mémoïsation (entrée vers<br/>
résultat), configuration<br/>
(option vers valeur).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Associer un identifiant à des informations, comme un nom à un âge</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est précisément le rôle<br/>
d'un dictionnaire. Il offre<br/>
une recherche rapide à<br/>
partir de la clé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Compresser efficacement de grandes quantités de données</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La compression de données<br/>
est une fonctionnalité<br/>
spécifique, sans lien<br/>
direct avec la structure de<br/>
dictionnaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Stocker une séquence ordonnée de notes d'élèves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pour ce cas, une liste est<br/>
plus adaptée. Le<br/>
dictionnaire excelle<br/>
plutôt pour l'association<br/>
entre une clé et une<br/>
valeur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Trier une liste de valeurs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le tri d'une liste est une<br/>
opération qui n'a rien à voir<br/>
avec les dictionnaires.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q10 : Clé fournie par une variable</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que produit ce code ?</p>
<p>`<code>python<br/>
nom = "Alice"<br/>
d = {"Alice": 17}<br/>
print(d[nom])<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La clé entre crochets est une expression quelconque :<br/>
un littéral (d["Alice"]), une variable (d[nom])<br/>
ou un calcul. Distinguer d[nom] (valeur de la<br/>
variable) de d["nom"] (chaîne littérale) évite<br/>
bien des KeyError.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il lève une KeyError, car nom n'est pas une clé de d</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : entre les crochets, Python évalue<br/>
d'abord l'expression nom, qui vaut<br/>
"Alice". C'est cette chaîne qui sert de clé,<br/>
et elle est bien présente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Il affiche 17</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : d[nom] équivaut à<br/>
d["Alice"], puisque nom contient la chaîne<br/>
"Alice". La valeur associée, 17, est<br/>
affichée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il affiche Alice</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'accès par clé renvoie la <strong>valeur</strong><br/>
associée, pas la clé elle-même. Alice n'est<br/>
que le contenu de la variable nom.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il lève une KeyError, car il manque les guillemets autour de nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : avec des guillemets, d["nom"]<br/>
chercherait la clé "nom", absente, et c'est<br/>
là que KeyError surviendrait. Sans<br/>
guillemets, nom est une variable dont la<br/>
valeur "Alice" sert de clé.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q11 : Compter les occurrences</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel code <strong>compte</strong> le nombre<br/>
d'occurrences de chaque mot dans<br/>
une liste mots ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Ce motif « tester puis créer ou incrémenter »<br/>
s'applique à tout comptage avec un dictionnaire :<br/>
la clé est l'objet compté, la valeur le nombre de<br/>
rencontres. Le test in évite la KeyError<br/>
qu'entraînerait la lecture d'une clé absente.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
c = {}<br/>
for m in mots:<br/>
    if m in c:<br/>
        c[m] = c[m] + 1<br/>
    else:<br/>
        c[m] = 1<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est le motif classique du<br/>
comptage. Le test m in c distingue la<br/>
première rencontre d'un mot (compteur créé<br/>
à 1) des suivantes (compteur incrémenté).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
c = {}<br/>
for m in mots:<br/>
    c[m] = c[m] + 1<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c[m] + 1 lit c[m] avant d'écrire.<br/>
À la première occurrence d'un mot, la clé<br/>
n'existe pas encore et Python lève KeyError.<br/>
Il manque le test if m in c.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
c = {}<br/>
for m in mots:<br/>
    if m in c:<br/>
        c[m] = c[m] + 1<br/>
    else:<br/>
        c[m] = 0<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la première occurrence est comptée<br/>
pour 0 au lieu de 1. Chaque mot finit avec<br/>
un compte inférieur d'une unité au vrai nombre<br/>
d'occurrences : sur ["a", "b", "a"], on<br/>
obtient {"a": 1, "b": 0} au lieu de<br/>
{"a": 2, "b": 1}.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
c = {}<br/>
for m in mots:<br/>
    c[m] = 1<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : chaque occurrence remet le compteur à<br/>
1 au lieu de l'incrémenter. À la fin, tous<br/>
les mots ont pour valeur 1.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q12 : Une valeur qui est une liste</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que produit ce code ?</p>
<p>`<code>python<br/>
d = {"fruits": ["pomme"]}<br/>
d["fruits"].append("poire")<br/>
print(d)<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une valeur de dictionnaire peut être une liste, un<br/>
tuple ou un autre dictionnaire. Comme<br/>
d["fruits"] renvoie l'objet lui-même, les<br/>
méthodes qui modifient une liste agissent<br/>
directement sur la valeur stockée.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Il affiche {'fruits': ['pomme', 'poire']}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : d["fruits"] renvoie la liste<br/>
rangée dans le dictionnaire, pas une copie.<br/>
L'appel append allonge donc cette liste, et<br/>
le changement est visible dans d.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il affiche {'fruits': ['pomme']}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'accès d["fruits"] ne copie pas la<br/>
liste. append agit sur l'objet même qui est<br/>
stocké dans le dictionnaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il affiche {'fruits': ['poire']}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : append ajoute un élément à la fin de<br/>
la liste sans effacer les autres. Seule une<br/>
affectation d["fruits"] = ["poire"]<br/>
remplacerait la valeur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il lève une AttributeError, car un dictionnaire n'a pas de méthode append</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la méthode n'est pas appelée sur d<br/>
mais sur d["fruits"], qui est une liste. Une<br/>
liste possède bien la méthode append.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q13 : Méthode items</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que renvoie l'appel d.items() ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Trois vues complémentaires sont<br/>
disponibles : keys() pour les<br/>
clés, values() pour les<br/>
valeurs, et items() pour les<br/>
paires. Elles sont<br/>
dynamiques : elles reflètent<br/>
les modifications du<br/>
dictionnaire au fur et à<br/>
mesure.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une liste contenant uniquement l'ensemble des clés</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette description correspond<br/>
plutôt à d.keys(). La<br/>
méthode items renvoie<br/>
autre chose.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un ensemble contenant les valeurs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pour obtenir les valeurs,<br/>
on utilise plutôt<br/>
d.values(). La méthode<br/>
items renvoie les paires<br/>
complètes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La taille du dictionnaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La taille du dictionnaire<br/>
s'obtient avec la fonction<br/>
len(d).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une vue itérable sur les paires (clé, valeur)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette vue permet d'itérer<br/>
sur les deux à la fois,<br/>
avec la syntaxe<br/>
for k, v in d.items():.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q14 : Clés autorisées dans un dictionnaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lequel des types suivants ne peut<br/>
<strong>pas</strong> être utilisé comme clé de<br/>
dictionnaire ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La règle est la suivante : la<br/>
clé doit être <strong>immuable</strong>.<br/>
Un tuple composé d'éléments<br/>
immuables est donc autorisé,<br/>
mais un tuple contenant une<br/>
liste ne l'est pas.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le type str (chaîne)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les chaînes sont sans<br/>
doute le type de clé le<br/>
plus utilisé dans la<br/>
pratique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le type tuple, à condition que tous ses éléments soient eux-mêmes utilisables comme clés</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un tuple est autorisé<br/>
comme clé tant que tous<br/>
ses éléments sont eux-mêmes<br/>
immuables.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Le type list (liste)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les listes sont <strong>mutables</strong>,<br/>
ce qui les empêche d'être<br/>
utilisées comme clés.<br/>
Tenter d'écrire<br/>
d[[1, 2]] = 5 provoque<br/>
une TypeError.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le type int (entier)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les entiers sont<br/>
parfaitement utilisables<br/>
comme clés de<br/>
dictionnaire.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q15 : Dictionnaire et liste</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour rechercher une valeur à<br/>
partir d'un identifiant (par<br/>
exemple « l'élève dont<br/>
l'identifiant est 42 »),<br/>
pourquoi préfère-t-on un<br/>
dictionnaire à une liste ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Compromis : le dictionnaire<br/>
consomme plus de mémoire<br/>
(table de hachage interne),<br/>
mais offre une recherche<br/>
très rapide. La liste, plus<br/>
compacte, est lente pour la<br/>
recherche par clé.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Pour la rapidité de l'accès par clé</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : l'accès par clé est en<br/>
O(1) en moyenne, contre O(n) pour<br/>
parcourir une liste. Sur de gros volumes de<br/>
données, la différence est<br/>
considérable. Pour un<br/>
million d'éléments, on<br/>
parle d'environ 1 µs<br/>
avec un dictionnaire,<br/>
contre plusieurs<br/>
millisecondes avec une<br/>
liste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'une liste ne peut pas contenir d'identifiants numériques</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est<br/>
fausse. Les listes<br/>
peuvent contenir tout<br/>
type de valeurs,<br/>
notamment des nombres.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour économiser une part importante de la mémoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Au contraire, un<br/>
dictionnaire occupe en<br/>
général plus de mémoire<br/>
qu'une liste équivalente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucune raison, les deux structures se valent pour cet usage</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : il existe une différence majeure<br/>
de performance. Avec une liste, il faut<br/>
parcourir les éléments un à un jusqu'à<br/>
trouver l'identifiant.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q16 : Représenter une table de traduction</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment représenter une <strong>table de traduction</strong> simple du<br/>
français vers l'anglais en<br/>
Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour une <strong>petite</strong> table de<br/>
traduction, un dictionnaire<br/>
simple convient. Pour des<br/>
bases volumineuses, on a<br/>
plutôt recours à une base<br/>
de données ou à des<br/>
fichiers indexés.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
{"chat": "cat", "chien": "dog"}<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On utilise un dictionnaire,<br/>
ce qui permet un accès<br/>
immédiat :<br/>
traduction["chat"]<br/>
renvoie "cat".</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
("chat", "cat")<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ce tuple ne contient<br/>
qu'un seul couple. Il ne<br/>
permet pas de stocker<br/>
l'ensemble des<br/>
traductions.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
["chat", "cat", "chien", "dog"]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette structure est une<br/>
liste plate qui ne<br/>
permet pas une recherche<br/>
rapide par mot<br/>
français. Il faudrait<br/>
parcourir la liste pour<br/>
retrouver la<br/>
traduction.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
chat = "cat"; chien = "dog"<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Définir une variable par<br/>
mot est très peu<br/>
pratique : la solution<br/>
ne passe pas à<br/>
l'échelle dès que le<br/>
nombre de mots<br/>
augmente.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q17 : Construction depuis deux listes</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>`<code>python<br/>
noms = ["Lou", "Max"]<br/>
ages = [16, 17]<br/>
d = {}<br/>
for i in range(len(noms)):<br/>
    d[noms[i]] = ages[i]<br/>
print(d)<br/>
</code>`<br/>
Que produit ce code ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le parcours par indice range(len(noms)) permet<br/>
d'apparier deux listes de même longueur, et<br/>
l'affectation d[cle] = valeur remplit le<br/>
dictionnaire entrée par entrée. C'est une façon<br/>
courante de construire un dictionnaire à partir de<br/>
données tabulaires.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Il affiche {'Lou': 16, 'Max': 17}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque tour, noms[i] fournit<br/>
la clé et ages[i] la valeur de même rang.<br/>
L'affectation d[cle] = valeur crée l'entrée<br/>
si la clé est absente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il affiche {16: 'Lou', 17: 'Max'}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : dans d[noms[i]] = ages[i],<br/>
l'expression entre crochets est la <strong>clé</strong>.<br/>
Ce sont donc les noms qui servent de clés et<br/>
les âges qui sont les valeurs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il affiche {0: 'Lou', 1: 'Max'}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'indice i ne sert qu'à lire les deux<br/>
listes au même rang ; il n'est jamais utilisé<br/>
comme clé. La clé est noms[i], une chaîne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il lève une KeyError, car les clés 'Lou' et 'Max' n'existent pas encore</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : KeyError ne concerne que la<br/>
<strong>lecture</strong> d'une clé absente. Ici on écrit<br/>
dans d, et l'affectation crée la clé si elle<br/>
n'existe pas.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q19 : Ordre des entrées</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Depuis Python 3.7, dans quel<br/>
ordre les entrées d'un<br/>
dictionnaire sont-elles<br/>
parcourues ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour un parcours <strong>trié par clé</strong>, on écrit<br/>
for k in sorted(d):. Pour<br/>
un parcours <strong>trié par valeur</strong>, on écrit<br/>
for k in sorted(d, key=d.get):.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Dans un ordre aléatoire à chaque exécution</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>L'ordre est en réalité<br/>
déterministe depuis<br/>
Python 3.7 : les<br/>
entrées sont parcourues<br/>
dans l'ordre où elles<br/>
ont été insérées.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Dans l'ordre d'insertion des paires</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est un changement<br/>
subtil mais important.<br/>
Avant Python 3.7,<br/>
l'ordre n'était pas<br/>
garanti, ce qui pouvait<br/>
surprendre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Dans l'ordre alphabétique des clés</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucun tri automatique sur<br/>
les clés n'est effectué.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Par taille croissante des valeurs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucun tri automatique<br/>
n'est effectué sur les<br/>
valeurs.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q20 : Cas du dictionnaire vide</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que vaut bool({}) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Convention dite « truthy /<br/>
falsy » : sont <strong>faux</strong><br/>
False, 0, 0.0, "",<br/>
[], {}, (), et<br/>
None. Tous les autres<br/>
objets sont considérés<br/>
comme <strong>vrais</strong> dans un<br/>
contexte booléen.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une exception</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le code est parfaitement<br/>
valide.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>False</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est la convention<br/>
Python : les structures<br/>
vides sont fausses.<br/>
C'est utile pour<br/>
tester rapidement avec<br/>
if d:, qui se lit<br/>
« si le dictionnaire<br/>
n'est pas vide ».</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La valeur 0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La fonction bool<br/>
renvoie un booléen, pas<br/>
un entier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>True</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un dictionnaire vide est<br/>
considéré comme faux en<br/>
Python, au même titre que<br/>
[], "", 0 et<br/>
None.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q23 : Modifier un dictionnaire pendant son parcours</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi est-il dangereux de<br/>
modifier un dictionnaire<br/>
pendant qu'on l'<strong>itère</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Règle générale : ne<br/>
<strong>jamais</strong> modifier une<br/>
collection (dictionnaire,<br/>
ensemble, liste, etc.)<br/>
pendant son parcours. Il<br/>
vaut mieux travailler sur<br/>
une copie ou collecter les<br/>
modifications dans une<br/>
structure auxiliaire.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que les modifications sont perdues à la fin du parcours</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les modifications ne sont pas<br/>
perdues. Le danger est que Python lève<br/>
RuntimeError si la taille change, ou que<br/>
le parcours devienne imprévisible.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que le dictionnaire est copié à chaque tour de boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune copie n'est faite. Le<br/>
parcours travaille sur le dictionnaire<br/>
lui-même, ce qui est justement le<br/>
problème.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucun danger, Python applique les modifications au tour suivant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python détecte le changement de<br/>
taille et lève RuntimeError au lieu de<br/>
continuer.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce que le parcours peut échouer ou devenir imprévisible</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : ajouter ou supprimer une<br/>
clé change la taille du dictionnaire ;<br/>
Python le détecte et lève RuntimeError<br/>
(« dictionary changed size during<br/>
iteration »). Pour modifier<br/>
en sécurité, il faut<br/>
itérer sur une <strong>copie</strong><br/>
de la liste des clés,<br/>
par exemple<br/>
for k in list(d):.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q25 : Synthèse</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Parmi les affirmations<br/>
suivantes sur les<br/>
dictionnaires, laquelle est<br/>
<strong>fausse</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Mémo utile : la clé d'un<br/>
dictionnaire doit être<br/>
stable dans le temps. Tout<br/>
ce qui est mutable n'est<br/>
donc pas autorisé comme<br/>
clé.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'opérateur in teste la présence d'une clé, pas celle d'une valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est<br/>
correcte. Sur un<br/>
dictionnaire, k in d<br/>
cherche k parmi les<br/>
clés ; pour les valeurs,<br/>
il faut écrire<br/>
v in d.values().</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'accès par clé est en O(1) en moyenne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est<br/>
correcte. C'est la<br/>
conséquence directe de<br/>
l'implémentation par<br/>
table de hachage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une liste peut être utilisée comme clé d'un dictionnaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est<br/>
fausse (donc c'est la<br/>
bonne réponse). Les<br/>
listes étant mutables,<br/>
elles ne peuvent pas<br/>
servir de clés. Seuls<br/>
les objets immuables<br/>
(entier, chaîne,<br/>
flottant, tuple,<br/>
ensemble figé) peuvent<br/>
être utilisés comme<br/>
clés.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Depuis Python 3.7, l'ordre d'insertion des paires est conservé lors du parcours</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est<br/>
correcte. C'est une<br/>
garantie introduite à<br/>
partir de Python 3.7.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q26 : Méthode values</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On dispose du dictionnaire suivant :</p>
<p>`<code>python<br/>
stock = {"stylo": 5, "cahier": 12, "gomme": 3}<br/>
</code></p>
<p>Que renvoie l'expression sum(stock.values())` ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Trois vues complémentaires sur un dictionnaire :<br/>
d.keys() (les clés), d.values() (les valeurs)<br/>
et d.items() (les couples). Combinées avec les<br/>
fonctions natives sum, max, min ou len,<br/>
elles permettent d'écrire des traitements concis.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La somme des longueurs des clés (16)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : values agit sur les valeurs, pas sur<br/>
les clés. La longueur des chaînes utilisées<br/>
comme clés n'intervient pas ici.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une erreur de type</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la fonction sum accepte parfaitement<br/>
un itérable de nombres. La méthode values<br/>
renvoie justement un itérable, donc<br/>
l'opération est valide.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>20</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : stock.values() renvoie une vue<br/>
sur les valeurs [5, 12, 3], et sum calcule<br/>
leur total : 5 + 12 + 3 = 20.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>3</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait le nombre de <strong>clés</strong>, soit<br/>
la longueur du dictionnaire (len(stock)).<br/>
La somme demandée porte sur les <strong>valeurs</strong>, pas<br/>
sur le nombre d'entrées.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q27 : Inverser un dictionnaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On souhaite, à partir d'un dictionnaire d aux<br/>
valeurs distinctes, construire un nouveau<br/>
dictionnaire inv où les clés et les valeurs sont<br/>
échangées. Quel code convient ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette technique ne fonctionne correctement que si<br/>
les valeurs sont uniques. Si plusieurs clés<br/>
partagent une même valeur, chaque affectation<br/>
inv[v] = k écrase celle déjà rangée sous cette<br/>
clé et une seule association survit. Pour un mappage<br/>
multivalué, il faudrait construire un dictionnaire<br/>
de listes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
inv = {}<br/>
for k in d:<br/>
    inv[v] = k<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la boucle for k in d ne fournit que<br/>
la clé k ; la variable v n'est définie nulle<br/>
part et Python lève NameError. Il faut<br/>
obtenir la valeur par d[k] ou par items().</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
inv = {}<br/>
for v in d.values():<br/>
    inv[v] = d[v]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la boucle parcourt les <strong>valeurs</strong> de<br/>
d, et d[v] cherche une valeur parmi les<br/>
clés, d'où une KeyError dès le premier tour.<br/>
Les valeurs ne sont pas des clés de d.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
inv = {}<br/>
for k, v in d.items():<br/>
    inv[v] = k<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : items() fournit chaque couple<br/>
(clé, valeur), dépaqueté dans k et v.<br/>
L'affectation inv[v] = k range le couple<br/>
inversé dans le nouveau dictionnaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
inv = {}<br/>
for k, v in d.items():<br/>
    inv[k] = v<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'affectation inv[k] = v recopie<br/>
chaque couple dans le même sens. On obtient une<br/>
copie de d, pas son inverse ; il faut<br/>
échanger les rôles avec inv[v] = k.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q28 : Construction depuis une liste de couples</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que renvoie l'expression<br/>
dict([("rouge", 1), ("vert", 2), ("bleu", 3)]) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Deux façons usuelles de créer un dictionnaire :<br/>
le littéral {"a": 1, "b": 2} et la fonction<br/>
dict appliquée à une liste de couples. Pour<br/>
bâtir un dictionnaire à partir de deux listes<br/>
parallèles cles et valeurs, on part d'un<br/>
dictionnaire vide d = {} et l'on écrit<br/>
for i in range(len(cles)): d[cles[i]] = valeurs[i].<br/>
La forme « liste de couples » est très utile lors<br/>
de la lecture de fichiers structurés.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>{'rouge': 1, 'vert': 2, 'bleu': 3}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la fonction dict accepte une<br/>
liste de couples (clé, valeur) et construit<br/>
le dictionnaire correspondant. C'est une façon<br/>
courante de bâtir un dictionnaire à partir de<br/>
données structurées (par exemple des couples<br/>
lus ligne par ligne dans un fichier).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'rouge', 'vert', 'bleu'}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : des accolades sans deux-points<br/>
formeraient un <strong>ensemble</strong>, un autre type de<br/>
collection qui n'est pas au programme. dict<br/>
produit un dictionnaire avec des clés <strong>et</strong><br/>
des valeurs ; il ne se limite pas aux clés.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une erreur de syntaxe</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la fonction dict est native en Python<br/>
et accepte plusieurs formes d'appel. La<br/>
construction depuis une liste de couples est<br/>
parfaitement valide.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[('rouge', 1), ('vert', 2), ('bleu', 3)]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait la liste d'origine inchangée.<br/>
La fonction native dict transforme cette liste<br/>
en un véritable dictionnaire.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q29 : Pourquoi un dictionnaire pour appartenir</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On dispose de dix mille valeurs distinctes et l'on doit,<br/>
pour chacune des nombreuses entrées suivantes lues au<br/>
clavier, déterminer si la valeur saisie figure dans la<br/>
collection. En Python, il est nettement plus efficace<br/>
de placer ces dix mille valeurs dans un <strong>dictionnaire</strong><br/>
(ou un ensemble) plutôt que dans une <strong>liste</strong>. Pourquoi ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>En pratique, on range les dix mille valeurs comme clés<br/>
d'un dictionnaire (par exemple d[valeur] = True dans<br/>
une boucle), puis chaque test s'écrit saisie in d.<br/>
L'ensemble évoqué dans l'énoncé est un autre type<br/>
Python, hors programme de première, qui ne stocke que<br/>
les clés sans valeur associée ; il repose sur la même<br/>
structure interne, une table de hachage qui transforme<br/>
chaque clé en un indice de tableau, d'où le temps moyen<br/>
constant.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce que la recherche d'une clé est en moyenne à temps constant (table de hachage), alors qu'une liste parcourt tous ses éléments</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : un dictionnaire (ou un ensemble)<br/>
repose sur une <strong>table de hachage</strong>. Tester<br/>
l'appartenance d'une valeur coûte en moyenne un<br/>
temps constant, indépendamment de la taille de la<br/>
collection. Une liste, au contraire, est parcourue<br/>
séquentiellement, ce qui donne un coût proportionnel<br/>
au nombre d'éléments dans le pire des cas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'un dictionnaire occupe systématiquement moins de mémoire qu'une liste de même taille</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est plutôt l'inverse. Un dictionnaire est<br/>
plus coûteux en mémoire (table interne avec des<br/>
cases vides). Le gain se situe sur la vitesse de<br/>
recherche, pas sur l'empreinte mémoire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'un dictionnaire est automatiquement trié, ce qui rend la recherche dichotomique</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un dictionnaire Python n'est pas trié sur<br/>
ses clés (il préserve l'ordre d'insertion depuis<br/>
Python 3.7, ce qui est différent). L'accès rapide<br/>
ne vient pas du tri mais du hachage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'une liste interdit les valeurs en double et que ce contrôle ralentit chaque recherche</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une liste accepte parfaitement les<br/>
doublons, ce sont les ensembles et les clés d'un<br/>
dictionnaire qui sont uniques. Et le contrôle<br/>
d'unicité n'est pas la raison de la rapidité.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Dictionnaires — Q30 : Liste impossible comme clé</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>L'instruction d = {[1, 2]: "premier"} provoque une<br/>
erreur TypeError: unhashable type: 'list'. En revanche,<br/>
d = {(1, 2): "premier"} est acceptée. Pourquoi cette<br/>
différence ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Règle générale en Python : seuls les objets immuables<br/>
peuvent servir de clés de dictionnaire. Les types<br/>
usuels acceptés sont les entiers, les flottants, les<br/>
chaînes, les booléens et les tuples dont les éléments<br/>
sont eux-mêmes hachables. Les listes et les<br/>
dictionnaires, modifiables, ne peuvent pas être des<br/>
clés.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce qu'une liste est modifiable : son hachage changerait et l'entrée deviendrait introuvable ; un tuple immuable a un hachage stable</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : un dictionnaire est implémenté par<br/>
une table de hachage. Chaque clé est stockée à<br/>
l'emplacement déterminé par sa <strong>valeur de hachage</strong>.<br/>
Si une clé pouvait changer après insertion, l'entrée<br/>
ne serait plus retrouvée, et la table deviendrait<br/>
incohérente. C'est pourquoi Python n'autorise que<br/>
des objets <strong>immuables</strong> comme clés.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'une liste occupe trop de mémoire alors qu'un tuple n'en utilise pas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le tuple consomme également de la mémoire,<br/>
simplement un peu moins qu'une liste. La raison du<br/>
refus n'est pas la taille mais la mutabilité.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'une liste ne peut contenir que des entiers, alors qu'un tuple peut contenir tout type de valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une liste peut contenir n'importe quel<br/>
type de valeur en Python (entiers, chaînes,<br/>
objets, autres listes, etc.).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que les tuples sont, en Python, les seuls objets ordonnés et hachables par construction</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : beaucoup d'autres objets sont hachables<br/>
en Python (entiers, flottants, chaînes, booléens).<br/>
Le critère est l'immuabilité, pas l'appartenance<br/>
à la famille des tuples.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
