partielle de la mise en forme de chaîne
Est-il possible de faire partielle de la chaîne de mise en forme avec les avancées de mise en forme de chaîne méthodes, semblable au modèle de chaîne de safe_substitute()
fonction?
Par exemple:
s = '{foo} {bar}'
s.format(foo='FOO') #Problem: raises KeyError 'bar'
Vous devez vous connecter pour publier un commentaire.
Vous pouvez tromper en partielle mise en forme par l'écrasement de la cartographie:
impression
Bien sûr, cette mise en place de base fonctionne correctement uniquement pour la base de cas.
{bar:1.2f}
__missing__()
, retourner une instance d'une classe personnalisée primordial__format__()
dans une manière de renvoyer l'original de l'espace réservé, y compris le format spec. La preuve de concept: ideone.com/xykV7Rstr.Template.safe_substitute()
🙂 en tout cas, retour au point, j'ai couru un peu tests sur l'approche que vous avez proposé, et il semble que l'échec de certains complexes de l'interpolation. J'aimerais avoir quelques conseils sur comment élégamment améliorer ce code afin de couvrir les cas de coin.Si vous savez dans quel ordre vous êtes à la mise en forme des choses:
L'utiliser comme ceci:
Vous ne pouvez pas spécifier
foo
etbar
dans le même temps - vous devez le faire de façon séquentielle.s.format(foo='FOO',bar='BAR')
puis j'ai toujours'FOO {bar}'
, n'importe quoi. Pourriez-vous préciser?Vous pouvez utiliser le
partial
fonction defunctools
qui est court, plus lisible et également décrit le mieux le codeur de l'intention:python from functool import partial s = "{foo} {bar}".format s_foo = partial(s, foo="FOO") print(s_foo(bar="BAR")) # FOO BAR print(s(foo="FOO", bar="BAR")) # FOO BAR
partial()
est ne va pas m'aider si j'ai besoin d'effectuer un traitement avec l'partiellement chaîne mise en forme (c'est-à"FOO {bar}"
)."{foo} {{bar}}".format(foo="{bar}").format(bar="123")
des autres exemples. Je m'attends à ce"{bar} 123"
mais ils de sortie"123 123"
.Cette limitation de
.format()
- l'impossibilité de faire des substitutions partielles - a été mise sur écoute-moi.Après l'évaluation de l'écriture personnalisée
Formatter
classe comme décrit dans beaucoup de réponses ici, et même en tenant compte de l'aide de paquets de tierce partie tels que lazy_format, j'ai découvert beaucoup plus simple intégré de la solution: Modèle de chaînes de caractèresIl offre des fonctionnalités similaires, mais fournit également une substitution partielle approfondie
safe_substitute()
méthode. Le modèle des chaînes besoin d'avoir un$
préfixe (qui se sent un peu bizarre, mais l'ensemble de la solution, je pense que c'est mieux).Formé une commodité wrapper sur cette base:
De même une enveloppe fondée sur Sven réponse qui utilise la valeur par défaut de la chaîne de mise en forme:
Ne sais pas si c'est ok comme une solution de rechange rapide, mais que diriez -
? 🙂
Si vous définissez vos propres
Formatter
qui remplace laget_value
méthode, vous pouvez l'utiliser pour la carte undefined noms de champ à ce que vous vouliez:http://docs.python.org/library/string.html#string.Formatter.get_value
Par exemple, vous pouvez mapper
bar
à"{bar}"
sibar
n'est pas dans la kwargs.Cependant, ce qui nécessite l'utilisation de la
format()
méthode de votre objet de Formatage, pas de la chaîneformat()
méthode.Essayer.
{{
et}}
est un moyen de s'en échapper, les marques de mise en forme, de sorteformat()
ne pas faire la substitution et remplace{{
et}}
avec{
et}
, respectivement.{{ }}
ne fonctionne que pour un seul format, si vous avez besoin d'appliquer de plus, vous devrez ajouter plus{}
. ex.'fd:{uid}:{{topic_id}}'.format(uid=123).format(a=1)
retourne l'erreur depuis le deuxième format est en ne fournissant pas lestopic_id
valeur.Grâce à Ambre's commentaire, je suis venu avec cette:
{field!s: >4}
devient{field}
Pour moi, c'était assez bon:
Ma suggestion serait la suivante (testé avec Python3.6):
Mise à jour:
Encore plus élégant (sous-classement
dict
et la surcharge__missing__(self, key)
) est indiqué ici: https://stackoverflow.com/a/17215533/333403En supposant que vous n'utilisez pas la chaîne jusqu'à ce qu'il soit complètement rempli, vous pourriez faire quelque chose comme cette classe:
Exemple:
Il y a un moyen de plus pour atteindre ce que je.e en utilisant
format
et%
de remplacer les variables. Par exemple:Une très laid, mais la solution la plus simple pour moi est de faire:
De cette façon, vous pouvez toujours utiliser
tmpl
régulière de modèle et d'effectuer partielle de la mise en forme uniquement lorsque cela est nécessaire. Je trouve ce problème trop banal pour utiliser un overkilling solution comme Mohan de Raj.Après l'essai de solutions les plus prometteuses de ici et il y, j'ai réalisé qu'aucun d'entre eux vraiment satisfait aux exigences suivantes:
str.format_map()
pour le modèle;Donc, j'ai écrit ma propre solution, qui satisfait aux exigences ci-dessus.
(MODIFIER: maintenant, la version par @SvenMarnach -- comme indiqué dans cette réponse semble gérer le coin des cas, j'avais besoin).
En gros, j'ai fini par l'analyse de la chaîne de modèle, de trouver des correspondants imbriquée
{.*?}
groupes (à l'aide d'unfind_all()
fonction d'assistance) et de la construction de la chaîne mise en forme progressivement et directement à l'aide destr.format_map()
lors de l'interception d'éventuelsKeyError
.(Ce code est également disponible dans FlyingCircus -- AVERTISSEMENT: je suis le principal auteur.)
L'utilisation de ce code serait:
Nous le comparons à la ma solution préférée (par @SvenMarnach qui a eu la gentillesse de partager son code ici et il y):
Ici sont un couple de tests:
et le code pour faire en cours d'exécution:
résultant dans:
comme vous pouvez le voir, la version mise à jour semble maintenant bien gérer le coin des cas où la version antérieure utilisé à l'échec.
Timewise, ils sont dans l'env. 50% de l'autre, en fonction de la réelle
text
de format (et probablement la réellesource
), maissafe_format_map()
semble avoir un avantage dans la plupart des tests que j'ai effectué (ce qu'ils signifient, bien sûr):{d[x]}
n'est pas un format valide chaîne autant que je suis conscient.field_name ::= arg_name ("." attribute_name | "[" element_index "]")*
et les deuxstr.format()
etstr.format_map()
comprendre. Je dirais qu'il y a suffisamment de preuves pour que cela soit valide chaîne de format.str.format()
avec un non-entier de l'indice entre crochets? Je ne peux que les index entiers de travail.a[b]
dans le code Python, mais il est en faita["b"]
Merci!{a["b"]}
toutstr.format_map()
besoins{a[b]}
pour accéder àa['b']
.Si vous souhaitez décompresser un dictionnaire pour passer des arguments à
format
, comme dans cette question, vous pouvez utiliser la méthode suivante.D'abord supposer la chaîne
s
est le même que dans cette question:et les valeurs sont données par le dictionnaire suivant:
Clairement cela ne fonctionne pas:
Cependant, vous pourriez d'abord obtenir un
set
de tous les arguments nommés à partir des
et de créer un dictionnaire des cartes que l'argument lui-même enveloppé dans des accolades:Maintenant utiliser le
args
dictionnaire de remplir les touches manquantes dansreplacements
. Pour python 3.5+, vous pouvez faire cela dans une seule expression:Pour les anciennes versions de python, vous pouvez l'appeler
update
:Vous peut encapsuler dans une fonction qui prend en arguments par défaut: