Es posible hacer parcial formato de cadena con la avanzada de la cadena de formato métodos, similar a la plantilla de cadena de safe_substitute() función?

Por ejemplo:

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

OriginalEl autor P3trus | 2012-07-01

13 Comentarios

  1. 42

    Se puede engañar a parcial formato sobreescribiendo la asignación:

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

    impresión

    FOO {bar}

    De este curso básico de aplicación sólo funciona correctamente básica casos.

    Esto no funciona para los más avanzados formattings como {bar:1.2f}
    Entiendo que dice que «el más básico de la aplicación sólo funciona correctamente para el basic de los casos», pero hay una manera de ampliar este incluso sólo para no eliminar el formato de especificación?
    Sí, hay una manera. En lugar de devolver una cadena en __missing__(), devolver una instancia de una clase personalizada primordial __format__() en una manera de devolver el original de marcador de posición, incluyendo el formato de especificaciones. Prueba de concepto: ideone.com/xykV7R

    OriginalEl autor Sven Marnach

  2. 91

    Si usted sabe en qué orden se está formateando cosas:

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

    Usarlo como este:

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

    No se puede especificar foo y bar al mismo tiempo que usted tiene que hacerlo de forma secuencial.

    ¿Cuál es el punto de esto? Si me especificar foo y bar: s.format(foo='FOO',bar='BAR') entonces yo todavía tengo 'FOO {bar}', no importa qué. Podrían aclarar?
    Que no se puede llenar ambas a la vez, es molesto. Esto es útil cuando, por cualquier razón, usted tiene el formato de una cadena de caracteres en etapas y saber el orden de las etapas.
    Probablemente, usted debe diseñar su manera de salir de tener que hacer esto, pero tal vez que se ve obligado a.
    +1 para un medio decente solución
    No sabía acerca de esto. He tenido varios casos de uso donde quería «prime» de una cadena como un mini plantilla

    OriginalEl autor aaren

  3. 38

    Esta limitación de .format() – la incapacidad para hacer sustituciones parciales – ha me ha estado molestando.

    Después de la evaluación de la escritura de una costumbre Formatter clase como se describe en muchas de las respuestas aquí y aún considerando el uso de paquetes de terceros, tales como lazy_format, he descubierto una forma mucho más simple incorporado solución: Plantilla de cadenas

    Proporciona una funcionalidad similar, pero también proporciona una sustitución parcial profundo safe_substitute() método. La plantilla de las cadenas de la necesidad de tener un $ prefijo (que se siente un poco raro – pero la solución general creo que es mejor).

    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'

    Formado una comodidad contenedor basa en esto:

    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

    Igualmente un contenedor basado en Sven respuesta que usa el valor predeterminado de cadena de formato:

    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)

    OriginalEl autor Mohan Raj

  4. 26

    Podría utilizar el partial función de functools que es corto, más legible y también describe mejor el codificador intención:

    from functools import partial
    
    s = partial("{foo} {bar}".format, foo="FOO")
    print s(bar="BAR")
    # FOO BAR
    No sólo es el más corto y más legible solución, sino que también describe el codificador intención. Python3 versión: 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
    cierto, la respuesta a las necesidades de un poco de amor 😉
    Bueno, no estoy seguro de que esto es exactamente lo que la mayoría de la gente está buscando. partial() no me va a ayudar si tengo que hacer algún proceso con la parte de formato de cadena (que es "FOO {bar}").
    Esto es mejor para el caso cuando usted está operando en la entrada que no el 100% del control. Imagina: "{foo} {{bar}}".format(foo="{bar}").format(bar="123") de los otros ejemplos. Yo esperaría "{bar} 123" pero la salida de "123 123".

    OriginalEl autor Saikiran Yerram

  5. 25

    No estoy seguro si esto es aceptar como una rápida solución, pero ¿

    s = '{foo} {bar}'
    s.format(foo='FOO', bar='{bar}')

    ? 🙂

    Estoy totalmente hicieron lo mismo, deseo sabía si hubo reparos en hacerlo.
    Inteligente! ……..
    Sí, eso funciona, sino que es simplemente molesto, especialmente si usted tiene varias teclas…

    OriginalEl autor Memphis

  6. 11

    Si usted define su propia Formatter que invalida el get_value método, se puede utilizar para mapa indefinido nombres de campo para todo lo que quería:

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

    Por ejemplo, usted podría mapa bar a "{bar}" si bar no está en la kwargs.

    Sin embargo, que requiere el uso de la format() método de su Formateador de objeto, no el de la cadena de format() método.

    Parece un python >= 2.6 función.

    OriginalEl autor Amber

  7. 9
    >>> 'fd:{uid}:{{topic_id}}'.format(uid=123)
    'fd:123:{topic_id}'

    A probar esto.

    Wow, exactamente lo que necesito! Podría usted explicar?
    {{ y }} es una manera de escapar de las marcas de formato, por lo que format() no realizar la sustitución y reemplaza {{ y }} con { y }, respectivamente.
    El problema de esta solución es que el doble {{ }} sólo funciona para un solo formato, si necesita aplicar más tendrá que agregar más {}. ex. 'fd:{uid}:{{topic_id}}'.format(uid=123).format(a=1) devolverá el error desde el segundo formato es el no facilitar los topic_id valor.

    OriginalEl autor Pengfei.X

  8. 7

    Gracias a Ambar‘s comentario, se me ocurrió esto:

    import string
    
    try:
        # Python 3
        from _string import formatter_field_name_split
    except ImportError:
        formatter_field_name_split = str._formatter_field_name_split
    
    
    class PartialFormatter(string.Formatter):
        def get_field(self, field_name, args, kwargs):
            try:
                val = super(PartialFormatter, self).get_field(field_name, args, kwargs)
            except (IndexError, KeyError, AttributeError):
                first, _ = formatter_field_name_split(field_name)
                val = '{' + field_name + '}', first
            return val
    Parece un python >= 2.6 función.
    Definitivamente estoy usando esta solución 🙂 Gracias!
    Ser conscientes de que esto va a perder la conversión y el formato de especificaciones, si existen (y que en realidad se aplica el formato de especificaciones para el valor devuelto. ie ({field!s: >4} se convierte en {field}

    OriginalEl autor gatto

  9. 3

    Para mí esto era lo suficientemente bueno:

    >>> ss = 'dfassf {} dfasfae efaef {} fds'
    >>> nn = ss.format('f1', '{}')
    >>> nn
    'dfassf f1 dfasfae efaef {} fds'
    >>> n2 = nn.format('whoa')
    >>> n2
    'dfassf f1 dfasfae efaef whoa fds'

    OriginalEl autor David Veza

  10. 0

    Suponiendo que usted no va a usar la cuerda hasta que es completamente llena, se podría hacer algo como esto: clase de

    class IncrementalFormatting:
        def __init__(self, string):
            self._args = []
            self._kwargs = {}
            self._string = string
    
        def add(self, *args, **kwargs):
            self._args.extend(args)
            self._kwargs.update(kwargs)
    
        def get(self):
            return self._string.format(*self._args, **self._kwargs)

    Ejemplo:

    template = '#{a}:{}/{}?{c}'
    message = IncrementalFormatting(template)
    message.add('abc')
    message.add('xyz', a=24)
    message.add(c='lmno')
    assert message.get() == '#24:abc/xyz?lmno'

    OriginalEl autor Brett Beatty

  11. 0

    Hay más de una forma de lograr este yo.e usando format y % reemplazar las variables. Por ejemplo:

    >>> s = '{foo} %(bar)s'
    >>> s = s.format(foo='my_foo')
    >>> s
    'my_foo %(bar)s'
    >>> s % {'bar': 'my_bar'}
    'my_foo my_bar'

    OriginalEl autor Moinuddin Quadri

  12. 0

    Una muy feo, pero es la solución más simple para mí es hacer:

    tmpl = '{foo}, {bar}'
    tmpl.replace('{bar}', 'BAR')
    Out[3]: '{foo}, BAR'

    Esta manera, usted todavía puede utilizar tmpl como plantilla y realizar parcial de formato sólo cuando sea necesario. Me parece que este problema es demasiado trivial para el uso de una destrucción excesiva de la solución como Mohan Raj.

    OriginalEl autor michcio1234

  13. -1

    Podría envolverlo en una función que toma predeterminado argumentos:

    def print_foo_bar(foo='', bar=''):
        s = '{foo} {bar}'
        return s.format(foo=foo, bar=bar)
    
    print_foo_bar(bar='BAR') # ' BAR'

    OriginalEl autor Trevor

Dejar respuesta

Please enter your comment!
Please enter your name here