Using .format() to format a list with field width arguments

前端 未结 2 865
轻奢々
轻奢々 2020-12-04 23:31

I recently (finally?) started to use .format() and have a perhaps a bit obscure question about it.

Given

res = [\'Irene Adler\', 35,  24         


        
相关标签:
2条回答
  • 2020-12-05 00:10

    The error message

    ValueError: cannot switch from manual field specification to automatic field numbering
    

    pretty much says it all: You need to give explicit field indices everwhere, and

    print('{0[0]:{1}s} {0[1]:{2}d} {0[2]:{3}f}'.format(res, 10, 5, .2))
    

    works fine.

    0 讨论(0)
  • 2020-12-05 00:19

    If you want to use .format(res, args), you can specify all indices in the format string like that:

    >>> print('{0[0]:{1[0]}s} {0[1]:{1[1]}d} {0[2]:{1[2]}f}'.format(res, args))
    Irene Adler    35 24.80
    

    But, if you want to make the format string without indices, you can create a tuple of consecutive pairs (res[0], args[0], ... , res[-1], args[-1]).

    This is done by this idiom:

    >>> sum(zip(res, args), ())
    ('Irene Adler', 10, 35, 5, 24.798, 0.2)
    

    You can now pass this into a simplified format string (via *-argument):

    >>> fmt = sum(zip(res, args), ())
    >>> print('{:{}s} {:{}d} {:{}f}'.format(*fmt))
    ('Irene Adler', 10, 35, 5, 24.798, 0.2)
    

    This can, of course, be done on one line:

    >>> print('{:{}s} {:{}d} {:{}f}'.format(*sum(zip(res, args), ())))
    Irene Adler    35 24.80
    

    To make it readable, I would name the transformation:

    def flat_pairs(iterable1, iterable2):
        return sum(zip(iterable1, iterable2), ())
    
    # (...)
    
    >>> print('{:{}s} {:{}d} {:{}f}'.format(*flat_pairs(res, args)))
    Irene Adler    35 24.80
    

    I think the last one is a reasonable trade-off between readability, convenience, and of course - showing off your Pythonic way of thinking, which is the primary motivation for playing with such stuff.

    0 讨论(0)
提交回复
热议问题