¿Cómo imprimir una cadena en ancho fijo?

103

Tengo este código (imprimiendo la ocurrencia de todas las permutaciones en una cadena)

def splitter(str):
    for i in range(1, len(str)):
        start = str[0:i]
        end = str[i:]
        yield (start, end)
        for split in splitter(end):
            result = [start]
            result.extend(split)
            yield result    

el =[];

string = "abcd"
for b in splitter("abcd"):
    el.extend(b);

unique =  sorted(set(el));

for prefix in unique:
    if prefix != "":
        print "value  " , prefix  , "- num of occurrences =   " , string.count(str(prefix));

Quiero imprimir toda la ocurrencia de permutación que haya en la cadena variable.

dado que la permutación no tiene la misma longitud, quiero arreglar el ancho e imprimirlo de una manera agradable no como esta:

value   a - num of occurrences =    1
value   ab - num of occurrences =    1
value   abc - num of occurrences =    1
value   b - num of occurrences =    1
value   bc - num of occurrences =    1
value   bcd - num of occurrences =    1
value   c - num of occurrences =    1
value   cd - num of occurrences =    1
value   d - num of occurrences =    1

¿Cómo puedo usar formatpara hacerlo?

Encontré estas publicaciones pero no fueron bien con cadenas alfanuméricas:

formato de cadena de Python ancho fijo

Configuración de longitud fija con Python

0x90
fuente
1
¿qué pasa con la impresión '% 10s'% 'mystring'
TJD
2
Sorprendido que "\t"no figura como opción en ninguna solución.

Respuestas:

113

EDITAR 2013-12-11 : esta respuesta es muy antigua. Sigue siendo válido y correcto, pero las personas que lo examinen deberían preferir la sintaxis del nuevo formato .

Puede usar un formato de cadena como este:

>>> print '%5s' % 'aa'
   aa
>>> print '%5s' % 'aaa'
  aaa
>>> print '%5s' % 'aaaa'
 aaaa
>>> print '%5s' % 'aaaaa'
aaaaa

Básicamente:

  • el %personaje le informa a Python que tendrá que sustituir algo a un token
  • el spersonaje le informa a Python que el token será una cadena
  • el 5(o el número que desee) informa a Python que rellene la cadena con espacios de hasta 5 caracteres.

En su caso específico, una posible implementación podría verse así:

>>> dict_ = {'a': 1, 'ab': 1, 'abc': 1}
>>> for item in dict_.items():
...     print 'value %3s - num of occurances = %d' % item # %d is the token of integers
... 
value   a - num of occurances = 1
value  ab - num of occurances = 1
value abc - num of occurances = 1

NOTA LATERAL: Me preguntaba si está al tanto de la existencia del itertoolsmódulo . Por ejemplo, podría obtener una lista de todas sus combinaciones en una línea con:

>>> [''.join(perm) for i in range(1, len(s)) for perm in it.permutations(s, i)]
['a', 'b', 'c', 'd', 'ab', 'ac', 'ad', 'ba', 'bc', 'bd', 'ca', 'cb', 'cd', 'da', 'db', 'dc', 'abc', 'abd', 'acb', 'acd', 'adb', 'adc', 'bac', 'bad', 'bca', 'bcd', 'bda', 'bdc', 'cab', 'cad', 'cba', 'cbd', 'cda', 'cdb', 'dab', 'dac', 'dba', 'dbc', 'dca', 'dcb']

y podría obtener el número de ocurrencias usando combinationsjunto con count().

Mac
fuente
24
Quizás debería mencionar que los números negativos dan una salida acolchada justificada a la izquierda; esto no es nada intuitivo para un principiante.
tripleee
+1 para @tripleee, sin tus números negativos, da un comentario justificado a la izquierda, me habría estado golpeando la cabeza por más tiempo ... gracias m8.
Briford Wylie
Esto es mucho más intuitivo y conciso que el nuevo formato str. No entiendo por qué hay este impulso en Python hacia la convolución
scottmrogowski
¿Hay alguna forma de completar los espacios en blanco con un carácter específico? Por ejemplo, si necesitamos imprimir "05" en lugar de "5"
Harshit Jindal
1
Aquí hay algunos trucos más para una impresión elegante de ancho fijo con cadenas de f en Medio .
pfabri
198

Encuentro usar str.formatmucho más elegante:

>>> '{0: <5}'.format('ss')
'ss   '
>>> '{0: <5}'.format('sss')
'sss  '
>>> '{0: <5}'.format('ssss')
'ssss '
>>> '{0: <5}'.format('sssss')
'sssss'

Si desea alinear la cadena con el uso correcto en >lugar de <:

>>> '{0: >5}'.format('ss')
'   ss'

Editar: como se menciona en los comentarios: el 0 indica el índice del argumento que se pasó str.format().

0x90
fuente
5
Además, el 0 indica la posición del argumento de formato, por lo que puede hacer otras dos cosas: '{<5}'.format('ss') 'ss 'al igual que antes, pero sin el 0, hace lo mismo o 'Second {1: <5} and first {0: <5}'.format('ss', 'sss') 'Second sss and first ss 'para que pueda reordenar o incluso generar la misma variable muchas veces en una sola salida cuerda.
mightypile
14
Ya no puedo editar el comentario anterior, que lo necesita. {<5}no funciona, pero {: <5}funciona sin el valor de índice.
mightypile
9
Aquí está el mini-lenguaje de especificación de formato de Python que describe estas cadenas de formato y opciones adicionales. Para referencia rápida, el espacio en {0: <5}es el [fill] , el <es [align]y 5es[width]
cod3monk3y
2
Ese 5 puede ser una sustitución variable>>> print width 20 >>> print "{0: <{width}}".format("ssssss", width=width).split('\n') ['ssssss '] >>>
user2763554
4
También puede usar números y simplemente enumerar las variables en orden width=10; "{0: <{1}}".format('sss', width). O incluso '{: <{}}'.format('sss', width)
omita
71

Publicado originalmente como una edición de la respuesta de @ 0x90, pero fue rechazado por desviarse de la intención original de la publicación y se recomendó publicarlo como comentario o respuesta, por lo que incluyo el breve artículo aquí.

Además de la respuesta de @ 0x90, la sintaxis se puede hacer más flexible, usando una variable para el ancho (según el comentario de @ user2763554):

width=10
'{0: <{width}}'.format('sss', width=width)

Además, puede hacer que esta expresión sea más breve, usando solo números y confiando en el orden de los argumentos pasados ​​a format:

width=10
'{0: <{1}}'.format('sss', width)

O incluso omita todos los números para una compacidad máxima, potencialmente no pitónicamente implícita:

width=10
'{: <{}}'.format('sss', width)

Actualización 2017-05-26

Con la introducción de literales de cadena formateados ("cadenas f" para abreviar) en Python 3.6, ahora es posible acceder a variables previamente definidas con una sintaxis más breve:

>>> name = "Fred"
>>> f"He said his name is {name}."
'He said his name is Fred.'

Esto también se aplica al formato de cadena

>>> width=10
>>> string = 'sss'
>>> f'{string: <{width}}'
'sss       '
joelostblom
fuente
¡Realmente me gusta más esta respuesta!
Syrtis Major
10

formates definitivamente la forma más elegante, pero afaik no puede usar eso con el loggingmódulo de python , así que así es como puede hacerlo usando el %formato:

formatter = logging.Formatter(
    fmt='%(asctime)s | %(name)-20s | %(levelname)-10s | %(message)s',
)

Aquí, -indica alineación a la izquierda y el número anterior sindica el ancho fijo.

Algunos resultados de muestra:

2017-03-14 14:43:42,581 | this-app             | INFO       | running main
2017-03-14 14:43:42,581 | this-app.aux         | DEBUG      | 5 is an int!
2017-03-14 14:43:42,581 | this-app.aux         | INFO       | hello
2017-03-14 14:43:42,581 | this-app             | ERROR      | failed running main

Más información en los documentos aquí: https://docs.python.org/2/library/stdtypes.html#string-formatting-operations

Ryntuck
fuente
Sin embargo, esto no acortará las cadenas por encima de los 20 caracteres. ¡Utilice lo '%(name)20.20s'que establece 20 como longitud de cuerda mínima y máxima!
xjcl
0
>>> print(f"{'123':<4}56789")
123 56789
Miladiouss
fuente