Форматирование строки python Столбцы в строке

Я пытаюсь отформатировать строку, чтобы все было между двумя.

APPLES                           $.99                           214                       
kiwi                             $1.09                           755 

Я пытаюсь это сделать:

fmt = ('{0:30}{1:30}{2:30}'.format(Fruit,price,qty))

Как мне получить столбец для выравнивания? Я читал документы, но я в замешательстве. Я думал, что {1:30} сделает это 30 пробелами, тогда он напечатает следующий элемент, но окажется, что это 30 пробелов, из которых закончился предыдущий элемент.

Спасибо

Ответ 1

str.format() делает ваши поля выравнивания влево в пределах доступного пространства. Используйте спецификаторы выравнивания, чтобы изменить выравнивание:

'<' Заставляет поле выравниваться по левому краю в пределах доступного пространства (это по умолчанию для большинства объектов).

'>' Заставляет поле выравниваться по правому краю в пределах доступное пространство (это значение по умолчанию для чисел).

'=' Заставляет отступы помещаться после знак (если есть), но перед цифрами. Это используется для печати полей в форме '+000000120. Этот параметр выравнивания действителен только для числовые типы.

'^' Заставляет поле быть центрированным в пределах доступное пространство.

Здесь пример (с выравниванием влево и вправо):

>>> for args in (('apple', '$1.09', '80'), ('truffle', '$58.01', '2')):
...     print '{0:<10} {1:>8} {2:>8}'.format(*args)
...
apple         $1.09       80
truffle      $58.01        2

Ответ 2

До сих пор я не знал, что у Python есть решение для форматирования столбцов - я решил изучить его на всякий случай, так как он уже создал свое собственное решение для другого языка, который не имеет встроенного решения (Lua) и Поскольку Logic является универсальной, я перенес ее на Python несколькими нажатиями клавиш.

Зная, что у Python есть собственное решение, я постараюсь интегрировать его в свое текущее решение.

Однако, поскольку я создал альтернативное решение, я опубликую свое решение здесь, чтобы вы могли увидеть, насколько удобное для меня мое решение - одна из моих жалоб с Python - это то, что некоторое форматирование менее интуитивно, например, Ternary Operator False, True (Честно говоря, True, False был бы лучшим порядком вместе с первым утверждением), а другие просто странные...

В примере функции показано использование Truncate (обратите внимание: некоторые логические затраты не требуются, но все еще движется - например, if _truncate... и т.д..), также показывая систему столбцов формата...

Это довольно просто - конвертировать вкладки в пробелы, подсчитывать длину столбцов, добавлять пробелы, если их слишком много, - если текста слишком много, тогда можно его нарезать (в моем другом решении есть буфер, который вы можете использовать, или границы, чтобы отображались символы границ, и заставить минимум 1 пустой символ между столбцами - у меня еще не было возможности добавить его в варианте Python) и т. д...

Это фантастика для отладки и вывода..

Есть несколько основных функций... String.FormatColumn([_width, _text],...), String.FormatSimpleColumn(_width, [_text,...] и String.FormatColumnEx(_empty_chars, [_width, _text],...)..

String.FormatSimpleColumn принимает ширину один раз и использует ее для всех столбцов, повторяет только текст.

String.FormatColumn принимает ширину и текст для каждого столбца...

String.FormatColumnEx - это то же самое, что и FormatColumn, за исключением того, что он позволяет указывать символы вместо пробелов - я обычно использую десятичные или другие символы для строки индекса....

для моей реализации Lua у меня также была возможность обрезать нужные пробелы, но в итоге я просто использовал вспомогательную функцию для обрезки, если пробелы не нужны... Я оставляю их, потому что если вы устанавливаете столбцы, вы можете просто добавить что-то в строку за пределами вызова функции, если вы хотите... и обрезка проста. Это также означает, что вы можете просто связать вызовы функций для получения одного и того же результата вместо объединения аргументов... в зависимости от того, что вам больше подходит...

##
## Sandbox - All Works, if public, are released under the ACL or Acecool Company License - Josh 'Acecool' Moser
##


##
## Declarations for Globals, CONSTants, ENUMeration, etc..
##

## Define the tab width in terms of how many space-chars are used per tab character - Pi uses 8, Windows uses 4, some use 2, etc..
CONST_TAB_WIDTH                             = 4


##
## String Library - This library only includes Format Column debugging output format system..
##
class String:


    ##
    ##
    ##
    def FormatColumnStripR( _width = 25, _text ='', *_varargs ):
        return String.FormatColumn( _width, _text, *_varargs ).rstrip( )


    ##
    ##
    ##
    def FormatSimpleColumnStripR( _width = 25, *_varargs ):
        return String.FormatSimpleColumn( _width, *_varargs ).rstrip( )


    ##
    ## Helper function which lets you define width for each text, and it repeats it for you so you can repeat text and all columns will be the same width
    ##
    ## Purpose:
    ##          The purpose of the Format Column Helpers is to improve data output, primarily for debugging so output is easier to follow..
    ## Usage:
    ##      String.FormatColumn( 25, 'Text / Key', 15, 'Some Value', 15, 'Another Key', 50, 'Another Value' )
    ##      String.FormatColumn( 25, 'Text / Key', 15, 'Some Value', 15, 'Another Key', 50, 'Another Value' )
    ##      String.FormatColumn( 25, 'Key', 15, 'Some', 15, 'Another', 50, 'Value' )
    ##
    ## Output:
    ##      Text / Key               Some Value     Another Key    Another Value                                     <LINE END>
    ##      Text / Key               Some Value     Another Key    Another Value                                     <LINE END>
    ##      Key                      Some           Another        Value                                             <LINE END>
    ##
    def FormatColumn( _width = 25, _text = '', *_varargs ):
        return String.FormatColumnEx( ' ', _width, _text, *_varargs )


    ##
    ## Helper function which lets you define width for each text, and it repeats it for you so you can repeat text and all columns will be the same width
    ##
    ## Purpose:
    ##          The purpose of the Format Column Helpers is to improve data output, primarily for debugging so output is easier to follow..
    ## Usage:
    ##      String.FormatColumnEx( '.', 25, 'Text / Key', 15, 'Some Value', 15, 'Another Key', 50, 'Another Value' )
    ##      String.FormatColumnEx( ' ', 25, 'Text / Key', 15, 'Some Value', 15, 'Another Key', 50, 'Another Value' )
    ##      String.FormatColumnEx( ' ', 25, 'Key', 15, 'Some', 15, 'Another', 50, 'Value' )
    ##
    ## Output:
    ##      Text / Key...............Some Value.....Another Key....Another Value.....................................<LINE END>
    ##      Text / Key               Some Value     Another Key    Another Value                                     <LINE END>
    ##      Key                      Some           Another        Value                                             <LINE END>
    ##
    def FormatColumnEx( _empty_char = ' ', _width = 25, _text = '', *_varargs ):
        ## Make sure our text is a string
        _text = str( _text )

        ## For each tab used, calculate how many spaces should be used with minimum of 1 and maximum of 4 being the range depending which snap-point is used.. Then strip that tab and add spaces in its place..
        _text = _text.expandtabs( CONST_TAB_WIDTH )

        ## Count how many additional arguments we have
        _count = len( _varargs )

        ## Since our Ex function, this, must use a paired-system, we make sure the rounded division is > 0
        _more = ( round( _count / 2, 0 ) > 0 )

        ## How many repeating chars do we need to create?
        _reps = ( _width - len( _text ) )

        ## Build a string to fill the empty column space with spaces so everything lines up - as long as the right font is used ( where all chars are the same size )
        _empty = _empty_char * _reps

        ## Now we ensure our text is limited to the _width size - data going over is truncated...TernaryFunc( _reps > 0, _empty, _empty )
        ## _data = String.SubStr( _text + ( _empty ), 0, _width )
        ## _data = ( _text + ( _empty ) )[  : _width ]
        _data = String.Truncate( _text + ( _empty ), _width )

        ## If we have more cars
        if ( _more ):
            ## Recursive call by shifting our VarArgs left so they populate _width and _text - then add the result to the data var... This only stops when no more paired options are left...
            _data = _data + String.FormatColumnEx( _empty_char, *_varargs )

        ## Return the data..
        return _data


    ##
    ## Helper function which lets you define width once, and it repeats it for you so you can repeat text and all columns will be the same width
    ##
    ## Purpose:
    ##          The purpose of the Format Column Helpers is to improve data output, primarily for debugging so output is easier to follow..
    ## Usage:
    ##      String.FormatSimpleColumn( 15, 'Text / Key', 'Some Value', 'Another Key', 'Another Value' )
    ##      String.FormatSimpleColumn( 15, 'Key', 'Some', 'Another', 'Value' )
    ##
    ## Output:
    ##      Text / Key     Some Value     Another Key    Another Value  <LINE END>
    ##      Key            Some           Another        Value          <LINE END>
    ##
    def FormatSimpleColumn( _width = 25, *_varargs ):
        ## Count how many text elements we have...
        _count = len( _varargs )

        ## Set up our return var
        _data = ''

        ## If we have at least 1 text element to set-up into a column
        if ( _count > 0 ):
            ## Then we loop through each vararg
            for _text in _varargs:
                ## If width is negative, use the length of the string plus the absolute value of width as a buffer...
                if ( _width < 0 ):
                    _data = _data + String.FormatColumn( len( str( _text ) ) + abs( _width ), str( _text ) )
                else:
                    ## And we use a pseudo recursive call on the FormatColumnEx function - extra args...
                    _data = _data + String.FormatColumn( _width, str( _text ) )

        ## Return the data..
        return _data


    ##
    ## SubString replacement
    ##
    ## Usage:
    ##      _data = String.SubStr( _text, 0, 10 )
    ##
    def SubStr( _text, _start, _end ):
        return _text[ _start : _end ]


    ##
    ## Truncate characters of a string after _len'nth char, if necessary... If _len is less than 0, don't truncate anything... Note: If you attach a suffix, and you enable absolute max length then the suffix length is subtracted from max length... Note: If the suffix length is longer than the output then no suffix is used...
    ##
    ## Usage: Where _text = 'Testing', _width = 4
    ##      _data = String.Truncate( _text, _width )                        == Test
    ##      _data = String.Truncate( _text, _width, '..', True )            == Te..
    ##
    ## Equivalent Alternates: Where _text = 'Testing', _width = 4
    ##      _data = String.SubStr( _text, 0, _width )                       == Test
    ##      _data = _text[  : _width ]                                      == Test
    ##      _data = ( _text )[  : _width ]                                  == Test
    ##
    def Truncate( _text, _max_len = -1, _suffix = False, _absolute_max_len = True ):
        ## Length of the string we are considering for truncation
        _len            = len( _text )

        ## Whether or not we have to truncate
        _truncate       = ( False, True )[ _len > _max_len ]

        ## Note: If we don't need to truncate, there no point in proceeding...
        if ( not _truncate ):
            return _text

        ## The suffix in string form
        _suffix_str     = ( '',  str( _suffix ) )[ _truncate and _suffix != False ]

        ## The suffix length
        _len_suffix     = len( _suffix_str )

        ## Whether or not we add the suffix
        _add_suffix     = ( False, True )[ _truncate and _suffix != False and _max_len > _len_suffix ]

        ## Suffix Offset
        _suffix_offset = _max_len - _len_suffix
        _suffix_offset  = ( _max_len, _suffix_offset )[ _add_suffix and _absolute_max_len != False and _suffix_offset > 0 ]

        ## The truncate point.... If not necessary, then length of string.. If necessary then the max length with or without subtracting the suffix length... Note: It may be easier ( less logic cost ) to simply add the suffix to the calculated point, then truncate - if point is negative then the suffix will be destroyed anyway.
        ## If we don't need to truncate, then the length is the length of the string.. If we do need to truncate, then the length depends on whether we add the suffix and offset the length of the suffix or not...
        _len_truncate   = ( _len, _max_len )[ _truncate ]
        _len_truncate   = ( _len_truncate, _max_len )[ _len_truncate <= _max_len ]

        ## If we add the suffix, add it... Suffix won't be added if the suffix is the same length as the text being output...
        if ( _add_suffix ):
            _text = _text[ 0 : _suffix_offset ] + _suffix_str + _text[ _suffix_offset: ]

        ## Return the text after truncating...
        return _text[ : _len_truncate ]


    ##
    ##
    ##
    def __example__( self ):
        ##
        ## Truncate Example...
        ##
        _col_key    = 20
        _col_eq     = 10
        _col_res    = 15
        _row_eq     = '=='
        _text       = 'Testing'
        print( '--------------------------------------------- 8' )
        _width = 8
        print( String.FormatColumn( _col_key, 'Testing',        _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width ) ) )
        print( String.FormatColumn( _col_key, 'Testing',        _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width, '..', True ) ) )
        print( '--------------------------------------------- 7' )
        _width = 7
        print( String.FormatColumn( _col_key, 'Testing',        _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width ) ) )
        print( String.FormatColumn( _col_key, 'Testing',        _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width, '..', True ) ) )
        print( '--------------------------------------------- 6' )
        _width = 6
        print( String.FormatColumn( _col_key, 'Testin',         _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width ) ) )
        print( String.FormatColumn( _col_key, 'Test..',         _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width, '..', True ) ) )
        print( '--------------------------------------------- 5' )
        _width = 5
        print( String.FormatColumn( _col_key, 'Testi',          _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width ) ) )
        print( String.FormatColumn( _col_key, 'Tes..',          _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width, '..', True ) ) )
        print( '--------------------------------------------- 4' )
        _width = 4
        print( String.FormatColumn( _col_key, 'Test',           _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width ) ) )
        print( String.FormatColumn( _col_key, 'Te..',           _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width, '..', True ) ) )
        print( '--------------------------------------------- 3' )
        _width = 3
        print( String.FormatColumn( _col_key, 'Tes',            _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width ) ) )
        print( String.FormatColumn( _col_key, 'T..',            _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width, '..', True ) ) )
        print( '--------------------------------------------- 2' )
        _width = 2
        print( String.FormatColumn( _col_key, 'Te',             _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width ) ) )
        print( String.FormatColumn( _col_key, '..',             _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width, '..', True ) ) )
        print( '--------------------------------------------- 1' )
        _width = 1
        print( String.FormatColumn( _col_key, 'T',              _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width ) ) )
        print( String.FormatColumn( _col_key, '.',              _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width, '..', True ) ) )
        print( '--------------------------------------------- 0' )
        _width = 0
        print( String.FormatColumn( _col_key, '',               _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width ) ) )
        print( String.FormatColumn( _col_key, '',               _col_eq, _row_eq,           _col_res, String.Truncate( _text, _width, '..', True ) ) )
        print( '---------------------------------------------' )

Ответ 3

Я думаю, что лучший способ это автоматически настроить ширину столбца от его содержимого

rows = [('apple', '$1.09', '80'), ('truffle', '$58.01', '2')]

lens = []
for col in zip(*rows):
    lens.append(max([len(v) for v in col]))
format = "  ".join(["{:<" + str(l) + "}" for l in lens])
for row in rows:
    print(format.format(*row))

Выход:

apple    $1.09   80
truffle  $58.01  2 

Демонстрация: https://code.sololearn.com/cttJgVTx55bm/#py