2011-03-15 18 views
87

Me gustaría crear un búfer de cadenas para hacer un montón de procesamiento, formatear y finalmente escribir el búfer en un archivo de texto usando una funcionalidad de estilo C sprintf en Python. Debido a las declaraciones condicionales, no puedo escribirlas directamente en el archivo.sprintf like funcionalidad en Python

por ejemplo seudo código:

sprintf(buf,"A = %d\n , B= %s\n",A,B) 
/* some processing */ 
sprint(buf,"C=%d\n",c) 
.... 
... 
fprintf(file,buf) 

Así que en el archivo de salida que tenemos este tipo de O/P:

A= foo B= bar 
C= ded 
etc... 

Editar, para aclarar mi pregunta:
buf es una El búfer grande contiene todas estas cadenas que se han formateado con sprintf. Según sus ejemplos, buf solo contendrá valores actuales, no más antiguos. por ejemplo, por primera vez en buf me escribió A= something ,B= something tarde C= something se adjunta en la misma buf, pero en su Python responde buf incluye solamente último valor, que no es que quiero - quiero buf que tienen todos los printf s que he hecho desde el principio, como en C.

+0

Esta es una gran pregunta, y creo que ninguna de estas respuestas se acercan a la solución de este. No deseo hacer algo como "% s% s% s"% (a, b, c), quiero proporcionar una lista de argumentos para una función y ver una cadena en la salida. – dividebyzero

+1

Esa no es la forma en que sprintf() funciona en C. (Escribe el contenido al principio de 'buf', no al final.) Probablemente funcione mejor usar una matriz de cadenas, luego unirlas antes de escribir al archivo. – yam655

Respuesta

33

Si entiendo su pregunta correctamente, format() es lo que está buscando, junto con its mini-language.

ejemplo tonto para Python 2.7 y hasta:

>>> print "{} ...\r\n {}!".format("Hello", "world") 
Hello ... 
world! 

Para versiones anteriores Python: (probado con 2.6.2)

>>> print "{0} ...\r\n {1}!".format("Hello", "world") 
Hello ... 
world! 
+4

Probablemente deberías notar que esa versión solo funciona en Python 3. En Python 2.6, por ejemplo, necesitas hacer: '" {0} ... \ r \ n {1}! ". Format (" Hello ", "mundo") ' –

+1

Editar mi respuesta para incluir eso; ¡No es que también funcione para Python 2.7! –

+0

Por supuesto, gracias :) –

8

Usted puede usar el formato de cadena:

>>> a=42 
>>> b="bar" 
>>> "The number is %d and the word is %s" % (a,b) 
'The number is 42 and the word is bar' 

Pero esto se elimina en Python 3, se debe utilizar "str.format()":

>>> a=42 
>>> b="bar" 
>>> "The number is {0} and the word is {1}".format(a,b) 
'The number is 42 and the word is bar' 
+4

Incorrecto, no se elimina en Python 3. Python 3.0 dijo que estaría en desuso en 3.1 pero creo que eso nunca sucedió. Es posible que sea preferible usar 'format()' pero aún existe el formato '%'. (Consulte http://mail.python.org/pipermail/python-dev/2009-September/092399.html para conocer algunos de los motivos por los cuales no se desaprobó) – Duncan

+1

@Duncan; gracias, no lo sabía. Leí en algún lugar que se depreció y nunca lo intenté de nuevo :). – utdemir

122

Python tiene un operador de % para esto.

>>> a = 5 
>>> b = "hello" 
>>> buf = "A = %d\n , B = %s\n" % (a, b) 
>>> print buf 
A = 5 
, B = hello 

>>> c = 10 
>>> buf = "C = %d\n" % c 
>>> print buf 
C = 10 

ver este reference para todos los especificadores de formato compatible.

Usted podría también utilizar format:

>>> print "This is the {}th tome of {}".format(5, "knowledge") 
This is the 5th tome of knowledge 
3

Ésta es probablemente la traducción más cercana a partir del código C para el código Python.

A = 1 
B = "hello" 
buf = "A = %d\n , B= %s\n" % (A, B) 

c = 2 
buf += "C=%d\n" % c 

f = open('output.txt', 'w') 
print >> f, c 
f.close() 

El operador % en Python hace casi exactamente lo mismo que C de sprintf. También puede imprimir la cadena a un archivo directamente. Si hay muchas de estas stringlets formateadas, podría ser aconsejable usar un objeto StringIO para acelerar el tiempo de procesamiento.

Así que en lugar de hacer +=, hacer esto:

import cStringIO 
buf = cStringIO.StringIO() 

... 

print >> buf, "A = %d\n , B= %s\n" % (A, B) 

... 

print >> buf, "C=%d\n" % c 

... 

print >> f, buf.getvalue() 
5

para insertar en una cadena muy larga que es agradable de usar los nombres de los diferentes argumentos, en vez de esperar que estén en las posiciones correctas. Esto también hace que sea más fácil reemplazar múltiples recurrencias.

>>> 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W') 
'Coordinates: 37.24N, -115.81W' 

Tomado de Format examples, donde también se muestran todas las otras respuestas Format relacionados con la PI.

11

No estoy completamente seguro de que entiendo su objetivo, pero se puede utilizar una instancia StringIO como un amortiguador:

>>> import StringIO 
>>> buf = StringIO.StringIO() 
>>> buf.write("A = %d, B = %s\n" % (3, "bar")) 
>>> buf.write("C=%d\n" % 5) 
>>> print(buf.getvalue()) 
A = 3, B = bar 
C=5 

A diferencia sprintf, que acaba de pasar una cadena a buf.write, formato con el % operador o el método format de cadenas.

Se podría definir, por supuesto, una función para obtener la interfaz sprintf usted está esperando:

def sprintf(buf, fmt, *args): 
    buf.write(fmt % args) 

que se utilizaría como esto:

>>> buf = StringIO.StringIO() 
>>> sprintf(buf, "A = %d, B = %s\n", 3, "foo") 
>>> sprintf(buf, "C = %d\n", 5) 
>>> print(buf.getvalue()) 
A = 3, B = foo 
C = 5 
+2

+1 para mostrarme cómo usar * args con el operador de formato de cadena (%). –

0

De acuerdo con (esta comparación de rendimiento), la comprensión de listas es la opción más rápida. Aquí es una aplicación orientada a objetos, que utiliza literal cadena de interpolación (también llamado F-String) introducido en Python 3.6:


class Buffer: 
    _buf = [] 

    def sprintf(self,s): 
     self._buf.append(s) 

    def fprintf(self,filename): 
     with open(filename,'w+') as file: 
      file.write(''.join([self._buf[i] for i in range(len(self._buf)) ])) 


def testBuffer(): 
    A = 1 
    B = "Hello" 
    C = "World" 
    buf = Buffer() 
    buf.sprintf("A = {A}\n , B = {B}\n") 
    buf.sprintf("C = {C}\n") 
    buf.fprintf("output.txt") 


testBuffer()