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
.