python python-3.x

python - ¿Cómo convertir% s en{0},{1}... menos torpe?



python-3.x (6)

¿Has probado con .format?

string.format (0 = valor, 1 = valor)

Entonces:

"A {0} B {1}".format(0=value, 1=value)

Tengo que tomar una cadena que contenga marcadores de posición para una sustitución posterior, como:

"A %s B %s"

Y convertir eso en:

"A {0} B {1}"

Se me ocurrio:

def _fix_substitution_parms(raw_message): rv = raw_message counter = 0 while ''%s'' in rv: rv = rv.replace(''%s'', ''{'' + str(counter) + ''}'', 1) counter = counter + 1 return rv

Eso funciona, pero se siente súper torpe, y en absoluto pitón "idiomático".

¿Cómo sería una solución de pitón bien idiomática?

Actualizaciones para aclaraciones:

  • Las cadenas resultantes no se utilizan en Python. ¡Necesito los números de mostrador allí! (¡entonces {} no es lo suficientemente bueno!)
  • Solo necesito preocuparme %s cadenas %s , ya que los mensajes están garantizados para usar solo %s (sin %i %f )

Creo que debería funcionar

rv.replace(''%s'',''{{{}}}'').format(*range(rv.count(''%s'')))


Haría lo que Reznik sugirió originally y luego llamaría a .format sobre eso:

def _fix_substitution_parms(raw_message: str) -> str: num_to_replace = raw_message.count("%s") python_format_string_message = raw_message.replace("%s", "{{{}}}") final_message = python_format_string_message.format(*range(num_to_replace)) return final_message


Usando re.sub para el reemplazo dinámico:

import re text = "A %s B %s %s B %s" def _fix_substitution_parms(raw_message): counter = 0 def replace(_): nonlocal counter counter += 1 return ''{{{}}}''.format(counter - 1) return re.sub(''%s'', replace, raw_message) print(_fix_substitution_parms(text)) # A {0} B {1} {2} B {3}


Usando un generador:

def split_and_insert(mystring): parts = iter(mystring.split(''%s'')) yield next(parts) for n, part in enumerate(parts): yield f''{{{n}}}'' yield part new_string = ''''.join(split_and_insert("A %s B %s"))


Use re.sub con una función lambda para volver a aplicar la sustitución una vez para cada elemento, y itertools.count para obtener números secuencialmente:

import itertools import re s = "A %s B %s" counter = itertools.count() result = re.sub(''%s'', lambda x: f''{{{next(counter)}}}'', s) print(result) # ''A {0} B {1}''

Recuerde incluir esto en una función para realizar esta operación más de una vez, ya que deberá actualizar itertools.count .