153 votes

formatage partiel de chaîne

Est-il possible d'effectuer un formatage de chaîne partiel avec les méthodes de formatage de chaîne avancées, similaire au modèle de chaîne safe_substitute() ?

Par exemple:

 s = '{foo} {bar}'
s.format(foo='FOO') #Problem: raises KeyError 'bar'
 

149voto

aaren Points 528

Si vous savez dans quel ordre vous formatez les choses:

 s = '{foo} {{bar}}'
 

Utilisez-le comme ceci:

 ss = s.format(foo='FOO') 
print ss 
>>> 'FOO {bar}'

print ss.format(bar='BAR')
>>> 'FOO BAR'
 

Vous ne pouvez pas spécifier foo et bar - simultanément - vous devez le faire de manière séquentielle.

67voto

Sven Marnach Points 133943

Vous pouvez le piéger en un formatage partiel en écrasant le mappage:

 import string

class FormatDict(dict):
    def __missing__(self, key):
        return "{" + key + "}"

s = '{foo} {bar}'
formatter = string.Formatter()
mapping = FormatDict(foo='FOO')
print(formatter.vformat(s, (), mapping))
 

impression

 FOO {bar}
 

Bien entendu, cette implémentation de base ne fonctionne correctement que dans des cas simples.

58voto

Mohan Raj Points 101

Cette limitation de l' .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: chaînes du Modèle

Il 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).

import string
template = string.Template('${x} ${y}')
try:
  template.substitute({'x':1}) # raises KeyError
except KeyError:
  pass

# but the following raises no error
partial_str = template.safe_substitute({'x':1}) # no error

# partial_str now contains a string with partial substitution
partial_template = string.Template(partial_str)
substituted_str = partial_template.safe_substitute({'y':2}) # no error
print substituted_str # prints '12'

Formé d'un confort wrapper sur cette base:

class StringTemplate(object):
    def __init__(self, template):
        self.template = string.Template(template)
        self.partial_substituted_str = None

    def __repr__(self):
        return self.template.safe_substitute()

    def format(self, *args, **kws):
        self.partial_substituted_str = self.template.safe_substitute(*args, **kws)
        self.template = string.Template(self.partial_substituted_str)
        return self.__repr__()


>>> s = StringTemplate('${x}${y}')
>>> s
'${x}${y}'
>>> s.format(x=1)
'1${y}'
>>> s.format({'y':2})
'12'
>>> print s
12

De même, un wrapper basé sur Sven réponse qui utilise la valeur par défaut de la chaîne de mise en forme:

class StringTemplate(object):
    class FormatDict(dict):
        def __missing__(self, key):
            return "{" + key + "}"

    def __init__(self, template):
        self.substituted_str = template
        self.formatter = string.Formatter()

    def __repr__(self):
        return self.substituted_str

    def format(self, *args, **kwargs):
        mapping = StringTemplate.FormatDict(*args, **kwargs)
        self.substituted_str = self.formatter.vformat(self.substituted_str, (), mapping)

11voto

Amber Points 159296

Si vous définissez vos propres Formatter qui remplace l' get_value méthode, vous pouvez l'utiliser pour la carte undefined noms de champ pour tout ce que tu voulais:

http://docs.python.org/library/string.html#string.Formatter.get_value

Par exemple, vous pouvez mapper bar de "{bar}" si bar n'est pas dans la kwargs.

Cependant, ce qui nécessite l'utilisation de l' format() méthode de votre objet de Formatage, pas la chaîne de l' format() méthode.

7voto

gatto Points 1674

Grâce au commentaire d’ Amber , j’ai trouvé ceci:

 class PartialFormatter(string.Formatter):
    def get_field(self, field_name, args, kwargs):
        try:
            val = super(PartialFormatter, self).get_field(field_name, args, kwargs)
        except (KeyError, AttributeError):
            first, _ = field_name._formatter_field_name_split()
            val = '{' + field_name + '}', first
        return val
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X