2012-07-12 15 views
6

Esto es sobre el mismo problema que en this question about floats.cadena de formato con “{0: d}” no convierte a entero

Cuando se tiene un valor que podría conseguir convertir en un entero, el viejo %d sería convertirlo, pero el formato no.

class MyIntegerTenClass: 
    def __int__(self): 
     return 10 
    def __str__(self): 
     return 'ten' 
ten = MyIntegerTenClass() 
print '%d, %02X, %s' % (ten, ten, ten) # ok 
print '{0}'.format(ten) # ok 
print '{0:d}, {0:02X}'.format(ten) # ValueError: Unknown format code 'd' for object of type 'str' 

¿Hay una manera de modificar el comportamiento de formato, sin tocar la clase del valor a ser formateado (sin añadir un método __format__ a esa clase)?

Editar: Mi objetivo es conseguir que el formato dependiente de la cadena de formato, pero no en el valor. lo tanto, si la cadena de formato dice "d" o "x", convertir el valor a int y luego a decimal o representación hexadecimal. Si la cadena de formato dice "s", conviértala directamente en cadena. Como lo hizo el antiguo %.

De hecho, podría incluso agregar un método __format__ a la clase del valor. ¿Pero cómo verifico, en ese método, si la especificación de formato dada es una especificación de formato entero? Sin volver a implementar el analizador de especificación de formato del formato incorporado.

Editar: Aquí hay una solución con __format__ y excepciones. Alguna mejor idea?

class MyIntegerTenClass: 
    def __int__(self): 
     return 10 
    def __str__(self): 
     return 'ten' 
    def __format__(self, spec): 
     fmt = '{0:%s}'%spec 
     try: 
      return fmt.format(str(self)) 
     except: 
      return fmt.format(int(self)) 
ten = MyIntegerTenClass() 
print '%d, %02X, %s' % (ten, ten, ten) # ok, prints "10, 0A, ten" 
print '{0:d}, {0:02X}, {0}'.format(ten) # ok, prints "10, 0A, ten" 
+1

Dice diez es una cadena, que está tratando de formato como un número. –

Respuesta

0

Una primera aproximación a este problema podría ser simplemente para try que:

class MyIntegerTenClass: 
    def __int__(self): 
     return 10 
    def __str__(self): 
     return 'ten' 
    def __format__(self, format_spec): 
     try: 
      s = format(str(self), format_spec) 
     except ValueError: 
      s = format(int(self), format_spec) 
     return s 

Si MyIntegerTenClasspuede insertarse en la cadena de formato como una cuerda, será. Si no, se convertirá en un int y se reenviará a format.

>>> print '{0}, {0:s}, {0:d}, {0:02X}, {0:f}'.format(ten) 
ten, ten, 10, 0A, 10.000000 

si desea que la representación por defecto para ser 10 en lugar de ten, sólo es necesario intercambiar las líneas de conversión: la salida

def __format__(self, format_spec): 
     try: 
      s = format(int(self), format_spec) 
     except ValueError: 
      s = format(str(self), format_spec) 
     return s 

prueba:

>>> print '{0}, {0:s}, {0:d}, {0:02X}, {0:f}'.format(ten) 
10, ten, 10, 0A, 10.000000 

Como una adición, me no creas que podrás obtener el comportamiento que deseas sin definir __format__; sin embargo, puede desarrollar un enfoque más sofisticado utilizando un objeto Formatter. Aún así, creo que el enfoque basado en excepciones le da mucha funcionalidad incorporada de forma gratuita.

+0

Gracias. Parece que obtuvimos la misma solución aproximadamente al mismo tiempo (ver mi segunda edición). Aunque su solución parece un poco más agradable ya que no necesita ese '{0:% s}'% espec. No me di cuenta de que hay una función de formato a la que puede llamar así. – Sebastian

1

pase un número entero en lugar de una cadena y funcionará bien.

>>> print '{0:d}'.format(1) 
1 
>>> print '{0:d}'.format('1') 

Traceback (most recent call last): 
    File "<pyshell#57>", line 1, in <module> 
    print '{0:d}'.format('1') 
ValueError: Unknown format code 'd' for object of type 'str' 
+2

Lo sabía. Pero no quiero pasar un número entero. Quiero pasar un objeto de mi clase que se puede convertir a un número entero. – Sebastian

0

Dice que diez es una cadena, está intentando formatearla como un número.

trate de envolver en un reparto:

>>> print '{0:d}, {0:02X}'.format(int(ten)) 
10, 0A 
+0

No funciona para mi caso de uso.No quiero cambiar el valor dado al formato. – Sebastian

Cuestiones relacionadas