## Python print() statements: part 4 f-strings This post is long overdue. In 2016, I wrote three posts on how to achieve well formatted print statements (1, 2, 3). However, on December 23, 2016, Python 3.6 was released, which added f-string.

### What are f-strings?

f-strings are a string formatting syntax. They are similar to `.format()` in that they allow us to generate well formatted strings. However, they are easier to read and write, and usually involve less typing.

### What can f-strings do?

f-strings can do everything `.format()` can, and more. Let’s start by updating some of the examples included in my previous posts to now use f-string.

Example from the first post:

``````num = 1
denom = 3
val = num/denom

# .format()
print('{} divided by {} equals {}'.format(num, denom, val))
# Revised to use f-strings
print(f'{num} divded by {denom} equals {val}')
``````

The output of both print statements is the same:

``````1 divded by 3 equals 0.3333333333333333
``````

Examples from the second post:

``````from math import pi

# .format()
print('Pi with 6 total spaces, including 5 digits after the decimal point {:6.5f}'.format(pi))
print('Pi with 2 total spaces, including 1 digits after the decimal point {:2.1f}'.format(pi))
print('Pi with 8 total spaces, including 1 digits after the decimal point {:8.1f}'.format(pi))

# Revised to use f-strings
print(f'Pi with 6 total spaces, including 5 digits after the decimal point {pi:6.5f}')
print(f'Pi with 2 total spaces, including 1 digits after the decimal point {pi:2.1f}')
print(f'Pi with 8 total spaces, including 1 digits after the decimal point {pi:8.1f}')
``````

The outputs are the same:

``````Pi with 6 total digits, including 5 digits after the decimal point 3.14159
Pi with 4 total digits, including 1 digits after the decimal point 3.1
Pi with 8 total digits, including 1 digits after the decimal point       3.1
``````

Examples from the third post:

``````# .format()

# Example 1
print('L {:<20} R'.format('x'))
# Example 2
print('L {:^20} R'.format('x'))
# Example 3
print('L {:>20} R'.format('x'))

# Revised to use f-strings

# Example 1
print(f'L {"x":<20} R')
# Example 2
print(f'L {"x":^20} R')
# Example 3
print(f'L {"x":>20} R')

``````

Same:

``````L x                    R
L          x           R
L                    x R
``````
``````# .format()
print ('{:=<20}'.format('hello'))
print ('{:_^20}'.format('hello'))
print ('{:|>20}'.format('hello'))

# Revised to use f-strings
print (f'{"hello":=<20}')
print (f'{"hello":_^20}')
print (f'{"hello":|>20}')

``````

Same:

``````hello===============
_______hello________
|||||||||||||||hello
``````
``````data = [['NAME', 'AGE', 'HANDEDNESS', 'SCORE (%)'],
['Martin', 38, 'L', 54.123],
['Marty', 33, 'L', 32.438],
['Martine', 25, 'R', 71.128],
['Martyn', 59, 'R', 50.472],
['Mart', 23, 'L', 2.438],
['Martyne', 15, 'R', 71.128],
['Marlyn', 101, 'R', 0.472],
['Marti', 2, 'L', 55.438],
['Mardi', 9, 'R', 81.128],
['Martyne', 49, 'R', 24.472],
['Marteen', 91, 'L', 1.128]]

dash = '-' * 40

# .format()
for i in range(len(data)):
if i == 0:
print(dash)
print('{:<10s}{:>4s}{:>12s}{:>12s}'.format(data[i], data[i], data[i], data[i]))
print(dash)
else:
print('{:<10s}{:>4d}{:^12s}{:>12.1f}'.format(data[i], data[i], data[i], data[i]))

# Revised to use f-strings
for i in range(len(data)):
if i == 0:
print(dash)
print(f'{data[i]:<10s}{data[i]:>4s}{data[i]:>12s}{data[i]:>12s}')
print(dash)
else:
print(f'{data[i]:<10s}{data[i]:>4d}{data[i]:>12s}{data[i]:>12.1f}')
``````

And, you guessed it, same:

``````----------------------------------------
NAME       AGE  HANDEDNESS   SCORE (%)
----------------------------------------
Martin      38           L        54.1
Marty       33           L        32.4
Martine     25           R        71.1
Martyn      59           R        50.5
Mart        23           L         2.4
Martyne     15           R        71.1
Marlyn     101           R         0.5
Marti        2           L        55.4
Mardi        9           R        81.1
Martyne     49           R        24.5
Marteen     91           L         1.1
``````

### What additional things can f-strings do?

f-strings are evaluated at runtime. That means we can use valid Python expressions in them. For example:

``````>>> f'The sum of 5 and 2 is {5+2}'
'The sum of 5 and 2 is 7'
>>> f'2 to the power of 10 is {2**10}'
'2 to the power of 10 is 1024'
>>> f'2 to the power of 8, 10, 12, 26 is {[2**power for power in [8, 10, 12, 16]]}'
'2 to the power of 8, 10, 12, 26 is [256, 1024, 4096, 65536]'
``````

You can also call functions within f-strings:

``````def remove_first_e(word):
found_e = False
revised_word = list()
for letter in word:
found_e = True
else:
revised_word.append(letter)
return ''.join(revised_word)

name = 'Martin Heroux'
print(f'{name} with the first e removed is {remove_first_e(name)}')

``````

The above will print:

``````Martin Heroux with the first e removed is Martin Hroux
``````

You can also use methods in f-strings:

``````name = 'marTin HeRoUx'
print(f'We will make {name} into allcaps, which produces {name.upper()}')
``````

The above will print:

``````We will make marTin HeRoUx into allcaps, which produces MARTIN HEROUX
``````

And, for long print statements, you can use multiple f-strings within the same statement:

``````# This won't work
mean, sd, min, max = 44, 7, 29, 79
print (f'The mean value is {mean}\n'
'The standard deviation is {sd}\n'
'The min is {min}\n'
'The max is {max}\n')

# But this will
print (f'The mean value is {mean}\n'
f'The standard deviation is {sd}\n'
f'The min is {min}\n'
f'The max is {max}\n')

``````

The incorrect version generates:

``````The mean value is 44
The standard deviation is {sd}
The min is {min}
The max is {max}
``````

Whereas the correct version generates:

``````The mean value is 44
The standard deviation is 7
The min is 29
The max is 79
``````

### Conclusion

As you can see, f-strings are super useful. Once you start using them you will never go back!