Python f-string
#
Find similar titles
- 최초 작성자
-
최근 업데이트
bjpark@insilicogen.com
Structured data
- Category
- Programming
Table of Contents
Overview #
Beginning with version 3.6, Python has a new type of string - f-string, which literally means "formatted string". These string improves the readability of the code, and also works faster than other methods of formatting. F-strings are specified using the literal "f" before the quotation marks.
>>> "simple string"
>>> f"f-string"
Methods #
Concatenation #
A rough way of formatting, in which we simply glue several lines using the addition operation:
>>> name = "John Doe"
>>> age = 25
>>> print("My name is " + name + ". I am " + str(age) + " years old.")
My name is John Doe. I am 25 years old.
% format #
The most popular way that has passed in Python from the C language. You can pass values to a string through lists and tuples, as well as using a dictionary. In the second case, the values are placed not by position, but in accordance with the names.
>>> name = "John Doe"
>>> age = 25
>>> print("My name is %s. I am %d years old." % (name, age))
My name is John Doe. I am 25 years old.
>>> print("My name is %(name)s. I am %(age)d years old." % {"name": name, "age": age})
My name is John Doe. I am 25 years old.
Template-string #
This method appeared in Python 2.4, as a replacement for% formatting (PEP 292), but it never became popular. Supports the transfer of values by name and uses $ -syntax as in PHP.
>>> from string import Template
>>> name = "John Doe"
>>> age = 25
>>> s = Template('My name is $name. I am $age years old.')
>>> print(s.substitute(name=name, age=age))
My name is John Doe. I am 25 years old.
Formatting with format()
method #
This method appeared in Python 3 as a replacement for % formatting. It also supports passing values by position and by name.
>>> name = "John Doe"
>>> age = 25
>>> print("My name is {}. I am {} years old.".format(name, age)
My name is John Doe. I am 25 years old.
>>> print("My name is {name}. I am {age} years old.".format(age=age, name=name)
Мy name is John Doe. I am 25 years old.
f-string #
The formatting that appeared in Python 3.6 (PEP 498). This method is similar to formatting using the format () method, but is more flexible, readable, and faster.
>>> name = "John Doe"
>>> age = 25
>>> print(f"My name is {name}. I am {age} years old.")
Мy name is John Doe. I am 25 years old.
Dive into f-string #
F-string does a very simple thing - it takes the values of the variables that are in the current scope, and substitutes them in a string. In the string itself, you only need to specify the name of this variable in curly brackets.
>>> name = "John Doe"
>>> age = 25
>>> print(f"My name is {name}. I am {age} years old.")
Мy name is John Doe. I am 25 years old.
F-string also supports extended formatting of numbers:
>>> from math import pi
>>> print(f"Value of number pi: {pi:.2f}")
Value of number pi: 3.14
We can also format the date without calling the strftime()
method:
>>> from datetime import datetime as dt
>>> now = dt.now()
>>> print(f"Current time is {now:%Y.%m.%d %H:%M}")
Current time is 2017.04.26 08:46
They support basic arithmetic operations. Yes, inside the string:
>>> x = 10
>>> y = 5
>>> print(f"{x} x {y} / 2 = {x * y / 2}")
10 x 5 / 2 = 25.0
It also allows us to access the values of lists by index:
>>> planets = ["Mercury", "Venus", "Earth", "Mars"]
>>> print(f"We live on the planet {planets[2]}")
We live on planet Earth
And also to the elements of the dictionary by the key:
>>> planet = {"name": "Earth", "radius": 6378000}
>>> print(f"Planet {planet ['name']}. Radius {planet ['radius'] / 1000} km.")
Planet Earth. Radius 6378.0 km.
And we can use both string and numeric keys. Just like in the usual Python code:
>>> digits = {0: 'zero', 'one': 'one'}
>>> print(f"0 - {digits [0]}, 1 - {digits ['one']}")
0 - zero, 1 - one
We can call the object methods in f-rows:
>>> name = "John Doe"
>>> print(f"Name: {name.upper()}")
Name: JOHN DOE
And also call functions:
>>> print(f"13 / 3 = {round(13/3)}")
13 / 3 = 4
F-string is very flexible and powerful tool for creating a wide variety of templates.
With all the possibilities of f-string you can read in PEP498 1.
Performance #
F-string are not only flexible, but also fast. And to compare the performance of different approaches to formatting, I prepared two templates:
-
Simple, in which you need to insert only two values: a string and a number;
-
Complex, the data for which are collected from different variables, and inside it converts the date, the real number, and rounding.
I wrote 5 functions, each of which returns a string formatted in one way, and after running each function many times.
And the final output string of simple benchmark is following:
Hi. My name is Alice. I am 10 years old.
And, this is code of simple benchmark:
import time
from random import shuffle, choice
from string import Template
def old_style(name, age):
return "Hi. My name is %s. I am %d years old." % (name, age)
def concat_style(name, age):
return "Hi. My name is " + name + ". I am " + str(age) + " years old."
def new_style(name, age):
return "Hi. My name is {}. I am {} years old.".format(name, age)
def template_style(name, age):
return Template("Hi. My name is $name. I am $age years old.").substitute(name=name, age=age)
def f_style(name, age):
return "Hi. My name is {name}. I am {age} years old."
if __name__ == "__main__":
styles = [concat_style, old_style, template_style, new_style, f_style]
shuffle(styles)
for style in styles:
t0 = time.time()
for i in range(300000):
style(choice(["Alice", "Bob", "Eve", "Oscar"]), choice([10, 20, 55, 76]))
t1 = time.time()
total = t1 - t0
print(style.__name__, total)
This is code of complex benchmark:
import time
from random import shuffle
from string import Template
from datetime import datetime as dt
year = 365.25
planet = {
"name": "Earth",
"radius": 6378000,
"mass": 5.9726*10**24
}
now = dt.now()
def old_style():
return "Today is %s.\n" \
"We live in a planet %s. Radius is %d km., weight is %.3e.\n" \
"Period of revolution of Earth around Sun is %d days." % (
now.strftime("%d.%m.%Y"),
planet["name"],
planet["radius"] / 1000,
planet["mass"],
round(year)
)
def concat_style():
return "Today is " + now.strftime("%d.%m.%Y") + ".\n" \
"We live in a planet " + planet["name"] + ". Radius is " + str(int(planet["radius"] / 1000)) + " km., weight is " + str(planet["mass"]) + "\n" \
"Period of revolution of Earth around Sun is " + str(round(year)) + " days."
def new_style():
return "Today is {now:%d.%m.%Y}.\n" \
"We live in a planet {name}. Radius is {radius} km., weight is {mass:.3e}\n" \
"Period of revolution of Earth around Sun is {year} days.".format(
now=now, name=planet["name"], radius=int(planet["radius"] / 1000), mass=planet["mass"], year=round(year))
def template_style():
return Template("Today is $now.\n"
"We live in a planet $name. Radius is $radius km., weight is $mass\n"
"Period of revolution of Earth around Sun is $year days.").substitute(
now=now.strftime("%d.%m.%Y"), name=planet["name"], radius=int(planet["radius"] / 1000),
mass=planet["mass"], year=round(year))
def f_style():
return f"Today is {now:%d.%m.%Y}.\n" \
f"We live in a planet {planet['name']}. Radius is {int(planet['radius'] / 1000)} km., weight is {planet['mass']:.3e}\n" \
f"Period of revolution of Earth around Sun is {round(year)} days."
if __name__ == "__main__":
styles = [concat_style, old_style, template_style, new_style, f_style]
shuffle(styles)
for style in styles:
t0 = time.time()
for i in range(100000):
style()
t1 = time.time()
total = t1 - t0
print(style.__name__, total)
After a short test I got the following results:
On simple examples, f-string shows the best results.
25% faster than the % format
and format()
method.
On complex examples, f-string behaves as well as % format
.
(The difference in favor of % format
does not exceed the error value).
But with respect to format()
method, f-string is 27% faster.
Conclusion #
If you are using Python 3.6 or later, it's time to use f-strings - they are flexible and fast.