This is an archived version of the course and is no longer updated. Please find the latest version of the course on the main webpage.

Formatting strings

We have also used f-strings (formatted string literals).

f-strings were introduced in Python 3.6 to make string formatting easier and more readable. Before f-strings, the two main methods for formatting strings are:

name = "Josiah"
count = 10
possession = "cars"

# Python 2 "old-style" strings
print("%s has %d %s." % (name, count, possession))

# Python 3 str.format()
print("{} has {} {}.".format(name, count, possession))
print("{name} has {count} {possession}.".format(name=name, 
                                                count=count, 
                                                possession=posession
                                               ))

(And no, I do not own any cars!)

We will not cover these old methods since they are no longer recommended (read this article if you are interested). It is enough to know f-strings are designed to fix the weaknesses of older methods.

In fact, I did not even know about f-strings until I started preparing for this course, and will be using it from now on!

print(f"{name} has {count} {possession}")

Multiple lines can be handled with paranthesis:

name = "Josiah"
age = "18"
occupation = "Senior Teaching Fellow"

profile = (
    f"Name: {name}\n"
    f"Age: {age}\n"
    f"Occupation: {occupation}"
)

print(profile)

You can have any expression in f-strings. Python will eval() whatever is between the curly braces at runtime (i.e. parse the string and run the string as code).

print(f"Multiplying count by 5 gives you {count * 5}")
print(f"Is count equal to 10? {count == 10}") 

You can also access indices of dictionaries or lists directly in f-strings. Be careful with the single and double quotes!

my_dict = {"key1": "value1"}
print(f"{my_dict['key1']}")

In fact, you can include any object (implement the __str__ or __repr__ magic methods for your custom classes if you want to output something more informative)

class MyClass:
    def __str__(self):
        return "an instance of MyClass"

print(f"This is {MyClass()}.")

You can also call functions directly inside f-strings (but assigning them to variables might make them much more readable).

numbers = [6,3,9,2,4,5]
print(f"Count: {len(numbers)}; Sum: {sum(numbers)}; Mean: {sum(numbers)/len(numbers)}") 

You can format floating point values.

pi = 3.14159265359
print(f"PI with three significant digits: {pi:.3}")
print(f"PI with three decimal points: {pi:.3f}")
print(f"PI with three significant digits, 9-character width is {pi:9.3}")
print(f"PI with three significant digits, 9-character width padded with 0 is {pi:09.3}")

And you can left/centre/right justify strings (giving a fixed length).

title = "Title"
print(f"| {title : <20} | {title : ^20} | {title : >20} |")

For Python>=3.8 only! f-string debugging: you can create self-documenting expressions with the = operator. The example will probably explain this better.

numbers = [6,3,9,2,4,5]
print(f"{sum(numbers) = }")