vacia una tuplas palabra metodos llenar listas lista imprimir elementos crear comando buscar agregar python string-formatting missing-data

python - una - Dejando los valores en blanco si no se pasa en formato str.



metodos de listas en python (5)

Me he encontrado con un problema bastante simple para el que no puedo encontrar una solución elegante.

Estoy creando una cadena usando str.format en una función que se pasa en un dict de sustituciones para usar para el formato. Quiero crear la cadena y formatearla con los valores si se pasan y dejarlos en blanco de lo contrario.

Ex

kwargs = {"name": "mark"} "My name is {name} and I''m really {adjective}.".format(**kwargs)

debería regresar

"My name is mark and I''m really ."

en lugar de lanzar un KeyError (que es lo que pasaría si no hacemos nada).

Avergonzado, ni siquiera puedo encontrar una solución poco elegante para este problema. Supongo que podría resolver esto simplemente no utilizando str.format , pero prefiero usar el incorporado (que en su mayoría hace lo que quiero) si es posible.

Nota: No sé de antemano qué claves se utilizarán. Estoy tratando de fallar con gracia si alguien incluye una llave pero no la pone en el dictado de Kwargs. Si supiera con una precisión del 100% qué claves se buscarán, simplemente las rellenaré y terminaré con ellas.


Aquí hay una opción que usa collections.defaultdict :

>>> from collections import defaultdict >>> kwargs = {"name": "mark"} >>> template = "My name is {0[name]} and I''m really {0[adjective]}." >>> template.format(defaultdict(str, kwargs)) "My name is mark and I''m really ."

Tenga en cuenta que ya no estamos usando ** para descomprimir el diccionario en argumentos de palabras clave, y el especificador de formato usa {0[name]} y {0[adjective]} , lo que indica que debemos realizar una búsqueda de clave en el primer argumento format() usando "name" y "adjective" respectivamente. Al usar defaultdict una clave faltante dará como resultado una cadena vacía en lugar de elevar un KeyError.


Para el registro:

s = "My name is {name} and I''m really {adjective}." kwargs = dict((x[1], '''') for x in s._formatter_parser()) # Now we have: `kwargs = {''name'':'''', ''adjective'':''''}`. kwargs.update(name=''mark'') print s.format(**kwargs) # My name is mark and I''m really .


Puede seguir la recomendación en PEP 3101 y usar un subclase Formateador:

import string class BlankFormatter(string.Formatter): def __init__(self, default=''''): self.default=default def get_value(self, key, args, kwds): if isinstance(key, str): return kwds.get(key, self.default) else: return string.Formatter.get_value(key, args, kwds) kwargs = {"name": "mark", "adj": "mad"} fmt=BlankFormatter() print fmt.format("My name is {name} and I''m really {adj}.", **kwargs) # My name is mark and I''m really mad. print fmt.format("My name is {name} and I''m really {adjective}.", **kwargs) # My name is mark and I''m really .

A partir de Python 3.2, puede utilizar .format_map como alternativa:

class Default(dict): def __missing__(self, key): return ''{''+key+''}'' kwargs = {"name": "mark"} print("My name is {name} and I''m really {adjective}.".format_map(Default(kwargs)))

que imprime:

My name is mark and I''m really {adjective}.


Quería agregar una solución bastante simple a la sustitución de los valores predeterminados necesarios.

import string class SafeDict(dict): def __init__(self, missing=''#'', empty='''', *args, **kwargs): super(SafeDict, self).__init__(*args, **kwargs) self.missing = missing self.empty = empty def __getitem__(self, item): return super(SafeDict, self).__getitem__(item) or self.empty def __missing__(self, key): return self.missing values = SafeDict(a=None, c=1}) string.Formatter().vformat(''{a} {c} {d}'', (), values) # '' 1 #''


Una forma de evitar el error clave es incluirlo en el dict pero dejarlo en blanco:

kwargs = {"name": "mark", "adjective": ""} "My name is {name} and I''m really {adjective}.".format(**kwargs)

Los argumentos de las palabras clave esperan que sean claves en los kwargs. Otra forma de hacerlo sería con argumentos posicionales:

"My name is {0} and I''m really {1}.".format("mark")

Impresiones "Mi nombre es Mark y soy realmente". Mientras

"My name is {0} and I''m really {1}.".format("mark","black")

Impresiones "Mi nombre es Mark y soy realmente negro".

Alternativamente, puedes atrapar el ValueError.