f-Lines Python

by Alex
f-Lines Python

Despite one of the Python principles that says, “There must be one – and preferably only one – obvious way to do something,” our beloved language has as many as four ways to format a string. That’s just the way it has been historically. This is the second lesson in a series on string formatting. It includes:

  1. String format statement
  2. Format() method
  3. f-Lines
  4. Template strings

In this lesson, we’ll be introduced to f-Lines. Python 3.6 introduces a new way to format strings: string interpolation (more commonly called “formatted string literals” or “f-Lines”). f-Lines provide the ability to use Python expressions within strings. This happens as follows: each expression is evaluated, then all parts of an f-String are converted separately into regular strings, then all parts are concatenated (concatenated into one). Formatted string literals, just like the .format() string method described in the previous lesson, support the formatting described in the __format__ attribute. You can recognize f-String literals by the “f” character at the beginning of the string before the opening quotation mark.

Simple syntax

To use formatted string literals, simply put an “f” in front of the string and put Python expressions in curly braces in the string. In the simplest case, these are variable names. Python, as always, delights in its brevity! Example:


language = 'Python'
percent = 100
print(f'-The best language is {language}.{n'
f'-{the best language} {\n}'
f'-{percentages}%!")
# Conclusion:
-The best language is Python.
-Exactly?
-100%!

As you can see, formatted string literals can be multi-line, but the “f” symbol must be at the beginning of each line. If you use a capital “F”, the interpreter will still understand you:


print(F'2 + 2 = {2 + 2}')
# Output:
2 + 2 = 4

I hope you’re as excited about this syntax as I am!

Arbitrary expressions

Note, in the previous example, we used the expression {2 + 2} in the line. It is evaluated first and then converted to a string. This, of course, opens up a lot of possibilities.


my_var = input('Enter and I'll multiply ')
print(f'{(my_var + " ") * 2}')
# Output:
Enter and I'll multiply Hello!
Hello! Hello!

You can also call functions. Here is a simplified solution from the input() tutorial:


first_number = int(input('Enter a number '))
first_character = int('enter a number ')
second_number = int(input('Enter a number '))
second_character = input('Enter a number')
third_number = int(input('Enter a number '))
def calculate(first_digit, operator, second_digit):
if operator == '+':
return first_digit + second_digit
if operator == '-':
return first_digit - second_digit
if operator == '*':
return first_digit * second_digit
if operator == '/':
try:
return first_digit / second_digit
except ZeroDivisionError:
print('You can't divide by zero - it's dangerous!')
print(f'{calculate(calculate(first_digit, first_digit, second_digit), second_digit, third_digit)}')
# Output:
Enter the number 2
Type the + sign
Type in number 2
Enter sign /
Enter number 3
1.3333333333333333

Note that this is a simplified solution. There is no check for the sequence of arithmetic operations, no check that a whole number is entered, etc. I leave it to you to work out these details on your own. You can also call object methods:


my_var = input('Enter and I'll multiply ')
print(f'{(my_var + ").split() * 2}')
# Output:
Enter and I'll split Hello!
['Hello!', 'Hello!']

You can even use objects created from classes using the f-string.


class Foo:
pass
print(f'{Foo()} is an instance of {Foo}')
# output:
is instance of

Let’s figure out what’s going on here. When you try to print an object, the interpreter refers to its __str__() and __repr__() methods. We can override one of them and get a nice output:


class Foo:
def __str__(self):
return 'Foo object'
print(f'{Foo()} is instance of {Foo}')
# Output:
Foo object is instance of

Multiline F-Strings

As mentioned, you can have multiline f-stringings, but if you forget to put an “f” at the beginning of each line, you will not get at all what you expect:


print(print(f'1 + 1 = {1 + 1}\n'
'2 + 2 = {2 + 2}')
# Output:
1 + 1 = 2
2 + 2 = {2 + 2}

But you have the option of using “f” before triple quotes, then it will work:


print(f"""1 + 1 = {1 + 1}
2 + 2 = {2 + 2}""")
# Output:
1 + 1 = 2
2 + 2 = 4

Speed

One of the goals of creating formatted string literals was to increase speed over the then-existing .format() string method. And that goal was achieved. Let’s check this statement:


import timeit
var_1 = timeit.timeit("""
language = 'Python'
percent = 100
'-The best language is %s. -Are you sure? -%d' % (language, percent) + '%!'
""", number=10000)
var_2 = timeit.timeit("""
language = 'Python'
percent = 100
'-The best language is {}. -Are you sure? {}'.format(language, percent) + '%!'
""", number=10000)
var_3 = timeit.timeit("""
language = 'Python'
percent = 100
f'-The best language is {language}. -Are you sure? {percentages}' + '%!
""", number=10000)
var_4 = timeit.timeit("""
language = 'Python'
percent = 100
'-The best language is ' + language + '. -Are you sure? ' + str(percent) + '%!'
""", number=10000)
time_sum = var_1 + var_2 + var_3 + var_4
var_1, var_2, var_3, var_4 = [round(i / time_sum * 100) for i in (var_1, var_2, var_3, var_4)]
print('String format statement: ', var_1, '%', sep='')
print('Method .format(): ', var_2, '%', sep='')
print('Formatted string literal: ', var_3, '%', sep='')
print('Concatenation: ', var_4, '%', sep='')
# Output:
String format statement: 26%
Method .format(): 31%
Formatted string literal: 17%
Concatenation: 27%

The concatenation here is just for illustration. As you can see, “f”-Lines win in speed. When you add call cycles, the difference remains the same:


import timeit
var_2 = timeit.timeit("""
language = 'Python'
percent = 100
'-The best language is {}. -Are you sure? {}'.format(language, percent) + '%!'
""", number=10000000)
var_3 = timeit.timeit("""
language = 'Python'
percent = 100
f'-The best language is {language}. -Are you sure? {percentages}' + '%!'
""", number=10000000)
time_sum = var_2 + var_3
var_2, var_3 = [round(i / time_sum * 100) for i in (var_2, var_3)]
print('Method .format(): ', var_2, '%', sep='')
print('Formatted string literal: ', var_3, '%', sep='')
# Output:
Method .format(): 65%
Formatted string literal: 35%

Python F-Lines: Details

At this point, we’ve learned why f-strings are so good, so you may already be interested in trying them out. Let’s look at a few details to keep in mind:

Quotes

You can use several kinds of quotes inside expressions. Make sure that you don’t apply the same type of quotes inside and outside the f-string. This code will work:


print(f'{"Python"}')
# Output:
Python

This one, too:


print(print(f"{"Python"}")
# Output:
Python

You can also apply triple quotes:


print(f"""{"Python"}""")
# Output:
Python

If you need to use the same type of quotation marks inside and outside the string, \can help you:


print(f'\'Lorem\' \'ipsum\' \'dolor\' \'sit\' \'amet\')
# Conclusion:
'Lorem' 'ipsum' 'dolor' 'sit' 'amet'

Dictionaries

Speaking of quotes, be careful when working with Python dictionaries. You can insert a dictionary value by its key, but the key and the string itself must be framed in different quotes:


arg_dict = {'language': 'Python', 'percent': 100}
print(f"-The best language is {arg_dict['language']}.\n"
print(f"-{arg_dict['language']}
f"-{arg_dict['проценты']}%!")
# Conclusion:
-The best language is Python.
-Exactly?
-100%!

Note the number of possible problems if you make an error in SyntaxError:


arg_dict = {'language': 'Python', 'percent': 100}
print(f'-The best language is {arg_dict['language']}.\n'
f'-{arg_dict['language']\n'
f'-{arg_dict['percent']}%!")
# Output:
File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.2\scratches\scratch_1.py", line 3
print(f'-The best language is {arg_dict['language']}.\n'
^
SyntaxError: f-string: unmatched '['
Process finished with exit code 1

Parentheses

You need to use double curly braces to make parentheses appear in the line:


print(f'-The best language is {{Python}}.{n'
f'-Exactly?
f'-{{100}}%!')
# Conclusion:
-The best language is {Python}.
-Exactly?
-{100}%!

Note that using triple curly brackets will cause only single brackets to appear in the string:


print(f'{{{1}}}')
# Output:
{1}

In general, here we have the same non-obvious behavior as the .format() string method:


print(f'{{{{{{{{1}}}}}}}}')
# Output:
{{{{1}}}}

Backslashes

Although backslashes can be used in a string, you can’t do it inside an expression:


print(print(f'{"1\n2"}')
# Output:
File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.2\scratches\scratch_1.py", line 1
print(f'{"1\n2"}')
^
SyntaxError: f-string expression part cannot include a backslash
Process finished with exit code 1

You can work this out by evaluating the expression beforehand and using the result in f lines:


temp = "1\n2"
print(f'{temp}')
# Output:
1
2

Interline comments

Expressions should not contain comments using an octotorpe (the “#” symbol). Otherwise, you will have a SyntaxError:


print(f'2 + 2 = {4 # probably}')
# Output:
File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.2\scratches\scratch_1.py", line 1
print(f'2 + 2 = {4 # probably}')
^
SyntaxError: f-string expression part cannot include '#'
Process finished with exit code 1

Formatting inserted expressions

Formatted string literals, like the .format() string method, support formatting:


print(f'2 + 2 = {2 + 2:010d}')
# Output:
2 + 2 = 0000000004
print(print(f'2 + 2 = {2 + 2:^010d}')
#Output:
2 + 2 = 0000400000
print(f'2 + 2 = {"four:.3}')
# Output:
2 + 2 = even
filler = '_'
alignment = '^'
width = 9
language = 'Python'
print(f "{"{language:{filler}{alignment}{width}}")
# Output:
__Python__

Related Posts

LEAVE A COMMENT