Impression d'une chaine de caractère en utilisant un dictionnaire pour le format
getudir78
Messages postés
28
Date d'inscription
Statut
Membre
Dernière intervention
-
trifou -
trifou -
Bonjour,
Je viens de mettre en ligne mon fichier maladroitement et je n'y ai joint aucun commentaire.
Dans ce cas d'école, j'imprime une chaîne de caractères de 3 façons différentes :
1 - les paramètres du format sont définis manuellement; ça marche.
2 - les paramètres du format sont extraits manuellement d'une liste de chaînes de caractères; ça marche.
3 - pour rendre le format automatique pour un nombre variable de chaînes de caractères, j'ai mis les paramètres du format dans un dictionnaire; le dictionnaire me paraît correct.
Par contre, quand je veux imprimer la même chaîne de caractères qu'en 1 - et 2 -, en utilisant .format(**dict_s), j'obtiens le message d'erreur suivant :
Je ne comprends pourquoi ça ne marche pas.
Si vous pouvez éclairer le débutant que je suis, je vous en remercie par avance.
Cordialement
--------------------------------------------------------------------------------------------------------------------------------------------------------
Voici le programme en question :
Je viens de mettre en ligne mon fichier maladroitement et je n'y ai joint aucun commentaire.
Dans ce cas d'école, j'imprime une chaîne de caractères de 3 façons différentes :
1 - les paramètres du format sont définis manuellement; ça marche.
2 - les paramètres du format sont extraits manuellement d'une liste de chaînes de caractères; ça marche.
3 - pour rendre le format automatique pour un nombre variable de chaînes de caractères, j'ai mis les paramètres du format dans un dictionnaire; le dictionnaire me paraît correct.
Par contre, quand je veux imprimer la même chaîne de caractères qu'en 1 - et 2 -, en utilisant .format(**dict_s), j'obtiens le message d'erreur suivant :
IndexError: Replacement index 1 out of range for positional args tuple
Je ne comprends pourquoi ça ne marche pas.
Si vous pouvez éclairer le débutant que je suis, je vous en remercie par avance.
Cordialement
--------------------------------------------------------------------------------------------------------------------------------------------------------
Voici le programme en question :
""" But : faire des tests de print avec .format """ print("") Texte_pour_impression = "Né à {1}; Etudes à {2}, premier poste d'ingénieur à {0}, c'est imprimé !" print("1 - arguments du format directs ") print(Texte_pour_impression.format("Capitale", "Trifouilly-les-oies", "Ville-grande")) print("") liste_ville = ["Capitale", "Trifouilly-les-oies", "Ville-grande"] print("2 - arguments du format dans une chaine de caractères ") print(Texte_pour_impression.format(liste_ville[0] ,liste_ville[1], liste_ville[2])) print("") print("arguments dans in dictionnaire") #création d'un dictionnaire pour les arguments du format d'impression dict_s = {} i = 0 for s in liste_ville : #dict_s[str(i)] = liste_ville[i] dict_s[str(i)] = liste_ville[i] i += 1 print("dictionnaire ainsi créé = ", dict_s, " type =",type(dict_s)) print("") print("3 - arguments du format dans le dictionnaire ci-dessus ") # Le print suivant donne une erreur que je ne comprends pas print(Texte_pour_impression.format(**dict_s))
Configuration: Windows / Firefox 71.0
A voir également:
- Replacement index 1 out of range for positional args tuple
- Spouleur d'impression - Guide
- Format epub - Guide
- Format factory - Télécharger - Conversion & Codecs
- Caractère ascii - Guide
- Télécharger dictionnaire larousse pdf gratuit - Télécharger - Dictionnaires & Langues
1 réponse
Bonjour,
Cela vient du fait que les keys du dict sont numériques, format n'accepte pas cela pour un dict.
Donc il faudrait faire pour au départ une simple liste
La même chose pour le dict
On pourrait croire que ça fonctionne comme on veut, sauf que non, car les dict sont par nature non ordonné.
Donc il faut trier pour obtenir la même chose que la liste de départ
Conclusion :
Il est préférable de ne pas utiliser de clef numérique pour les dict surtout si on a besoin de l'afficher avec format ^^
Cela vient du fait que les keys du dict sont numériques, format n'accepte pas cela pour un dict.
Donc il faudrait faire pour au départ une simple liste
s = '{1} {0} {2} {4} {3}' digits = ['zéro', 'un', 'deux', 'trois', 'quatre'] print('Format list', s) print(s.format(*digits))
La même chose pour le dict
dic = {i:v for i, v in enumerate(digits)} print('Format dict', s) print(s.format(*dic.values()))
On pourrait croire que ça fonctionne comme on veut, sauf que non, car les dict sont par nature non ordonné.
dic = {i:v for i, v in enumerate(digits[1:], 1)} dic[0] = digits[0] print(s.format(*dic.values()))
Donc il faut trier pour obtenir la même chose que la liste de départ
print(s.format(*(dic[i] for i in sorted(dic))))
Conclusion :
Il est préférable de ne pas utiliser de clef numérique pour les dict surtout si on a besoin de l'afficher avec format ^^
Merci pour ton analyse détaillée qui m’a permis d’y voir clair et de résoudre mon problème d’impression. Pour faire le point, si j’ai bien compris :
- 1 - quand on crée un dictionnaire, l’ordre des clés utilisées pour sa construction se retrouve dans le dictionnaire qui en est le reflet. A sa création, le dictionnaire est alors ordonné et le restera si on ne le modifie pas
- 2 - quand on rajoute un nouvel item au dictionnaire, l’ordre n’est plus certain et il faut alors ordonner les clés par une fonction anonyme, pour retrouver l’ordre souhaité.
- 3 - *dictionnaire donne à toutes les clés du dictionnaire et *dictionnaire.values() parcourt les valeurs correspondantes.
-
Peux-tu me confirmer qu’il en est bien ainsi ?
Il reste un point mystérieux concernant les ** appliquées à des dictionnaires: Les clés du dictionnaire que j’ai créé, ne sont pas des entiers mais des strings d’entiers ; par exemple la clé d’indice 0 n’est pas 0 mais ‘0’, qui est donc un caractère.
Néanmoins, **dictionnaire crée une erreur d’indice ; :
IndexError: Replacement index 1 out of range for positional args tuple
Puisque les clés ne sont pas des entiers, d’où provient cette erreur ?
L’essentiel, c’est que maintenant, je dispose d une solution claire et viable pour imprimer du texte avec un format utilisant un dictionnaire.
Sois-en encore remercié.
Tous mes remerciements également à « Comment ça marche » pour ce remarquable forum.
Cordialement
Si on souhaite toujours avoir un dict ordonné par clés, il faut se tourner vers la classe OrderedDict du module collections.
Oui c'est ça pour *dictionnaire, c'est un raccourci de *dictionnaire.keys()
Puisque les clés ne sont pas des entiers, d’où provient cette erreur ?
En fait, ce n'est pas spécifique aux entiers, mais à toute clé de dictionnaire non conforme, elle doit avoir les mêmes règles d'écriture que la déclaration d'une variable typique pour pouvoir être utilisée avec format.
https://docs.python.org/3/library/string.html#format-string-syntax
... it is not possible to specify arbitrary dictionary keys (e.g., the strings '10' or ':-]') within a format string.
C'est pareil aux règles des arguments nommés des fonctions finalement.
Merci pour toutes ces infos précises.
Je ne vais pas trop dans la doc de Python parce qu'elle n'est pas toujours simple à comprendre Je devrais néanmoins m'y plonger dans l'espoir que ça finira par s'éclaircir.
Comme je travaille avec Python 3.8, je bénéficie des propriétés d'ordre des dictionnaires qui sont nouvelles, ce dont je n'avais pas conscience; mais c'est dangereux car si mon modeste code s'exécute sur une version antérieure, ça ne fonctionnera plus.
La doc est sans appel, ** ne peut pas s'appliquer au dictionnaire que j'ai créé, à cause des clés du type {'entier'}
En ce qui concerne les impressions de chaînes de caractères utilisant .format(), j'ai finalement trouvé un raccourci très simple :
"chaîne de caractère".format(*liste ).
Pour les exemples que tu proposes, ça serait
print(s.format(*digits))
et pour les impressions de mon programme test, ça donnerait
print(Texte_pour_impression.format(*liste_ville)).
C'est plus simple que de construire un dictionnaire, mais je ne sais pas ce que ça donne avec les versions antérieures de Python.
Que penses-tu de ce raccourci pour créer les bons arguments à .format() ?
Cordialement,
Tout dépend du contexte du code, on n'a généralement pas besoin de formater une chaîne avec format pour qu'elle soit compatible à la fois avec différents types de structures en paramètres, et généralement on utilise autre chose comme clés d'un dictionnaire que de simples numériques. Même si on peut le faire, on aura sans doute jamais besoin de passer un dictionnaire de ce type directement à format.