Using variables in the format() function in Python
Asked Answered
M

4

32

Is it possible to use variables in the format specifier in the format()-function in Python? I have the following code, and I need VAR to equal field_size:

def pretty_printer(*numbers):
  str_list = [str(num).lstrip('0') for num in numbers]

  field_size = max([len(string) for string in str_list])

  i = 1
  for num in numbers:
    print("Number", i, ":", format(num, 'VAR.2f')) # VAR needs to equal field_size
Manchu answered 5/9, 2015 at 12:35 Comment(0)
S
55

You can use the str.format() method, which lets you interpolate other variables for things like the width:

'Number {i}: {num:{field_size}.2f}'.format(i=i, num=num, field_size=field_size)

Each {} is a placeholder, filling in named values from the keyword arguments (you can use numbered positional arguments too). The part after the optional : gives the format (the second argument to the format() function, basically), and you can use more {} placeholders there to fill in parameters.

Using numbered positions would look like this:

'Number {0}: {1:{2}.2f}'.format(i, num, field_size)

but you could also mix the two or pick different names:

'Number {0}: {1:{width}.2f}'.format(i, num, width=field_size)

If you omit the numbers and names, the fields are automatically numbered, so the following is equivalent to the preceding format:

'Number {}: {:{width}.2f}'.format(i, num, width=field_size)

Note that the whole string is a template, so things like the Number string and the colon are part of the template here.

You need to take into account that the field size includes the decimal point, however; you may need to adjust your size to add those 3 extra characters.

Demo:

>>> i = 3
>>> num = 25
>>> field_size = 7
>>> 'Number {i}: {num:{field_size}.2f}'.format(i=i, num=num, field_size=field_size)
'Number 3:   25.00'

Last but not least, of Python 3.6 and up, you can put the variables directly into the string literal by using a formatted string literal:

f'Number {i}: {num:{field_size}.2f}'

The advantage of using a regular string template and str.format() is that you can swap out the template, the advantage of f-strings is that makes for very readable and compact string formatting inline in the string value syntax itself.

Spoil answered 5/9, 2015 at 12:37 Comment(2)
@MartijnP: Can't python do this? fmt='10.5f'; print(f'variance = {variance:fmt}')Parthia
@JoonhoPark yes, Python can do that provided you use a nested replacement part: print(f'variance = {variance:{fmt}}'). Demo: repl.it/repls/CommonBlaringLegacysystem#main.pySpoil
G
8

I prefer this (new 3.6) style:

name = 'Eugene'
f'Hello, {name}!'

or a multi-line string:

f'''
Hello,
{name}!!!
{a_number_to_format:.1f}
'''

which is really handy.

I find the old style formatting sometimes hard to read. Even concatenation could be more readable. See an example:

'{} {} {} {} which one is which??? {} {} {}'.format('1', '2', '3', '4', '5', '6', '7')
Generalship answered 9/6, 2021 at 7:46 Comment(1)
@crypdick Yes it does: {a_number_to_format:.1f}Fred
C
0

I used just assigned the VAR value to field_size and change the print statement. It works.

def pretty_printer(*numbers):
  str_list = [str(num).lstrip('0') for num in numbers]

  field_size = max([len(string) for string in str_list])

  VAR=field_size

  i = 1
  for num in numbers:
      print("Number", i, ":", format(num, f'{VAR}.2f'))
Cauley answered 19/8, 2020 at 11:34 Comment(0)
U
0

Now that we're up to python 3.12, double nested f strings do the trick as well, and are exceptionally compact:

r = 1.0234
fc = ".3f"
print(f"r = {r:{fc}}")

output

r = 1.023

Unthinking answered 5/6 at 21:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.