F-strings появились в Python 3.6 и стали очень удобным и полезным инструментов для форматированного вывода. Но они обладают некоторыми особенностями, о которых не все знают. Поэтому в этой статье остановимся на них
Форматированный вывод дат и времени
Подготовка данных для Data Mining на Python
Код курса
DPREP
Ближайшая дата курса
по запросу
Продолжительность
32 ак.часов
Стоимость обучения
72 000 руб.
Для нужного представления даты в виде строки согласно шаблону обычно используется функция strftime
(см. тут). Причем есть еще функция strptime
, и их нужно не путать. Но знали ли, что это можно сделать обычным f-strings? Пример кода на Python:
import datetime today = datetime.datetime.today() print(f"{today:%Y-%m-%d}") # 2022-04-05 print(f"{today:%Y}") # 2022
“По-честному” то же самое можно было бы сделать вот так:
print(today.strftime("%Y-%m-%d"))
Узнать, какие шаблоны для даты и времени можно через man-страницу: man strftime
.
Форматированный вывод имен
Начиная с Python 3.8, появилась возможность выводить имена переменных вместе с их значением через f-strings:
x = 10 y = 25 print(f"x = {x}, y = {y}") # x = 10, y = 25 print(f"{x = }, {y = }") # Лучше! (3.8+) # x = 10, y = 25 print(f"{x=}, {y=}") x=10, y=25 print(f"{x = :.3f}") # x = 10.000
Эта особенность называется отладкой (debugging). Она позволяет писать немного меньше кода.
Магические методы __repr__
и __str__
Если вы передадите в функцию print
экземпляр класса, то только узнаете имя класса, которому он принадлежит. Чтобы сделать форматированный вывод более информативным, используются магические методы __repr__
и __str__
. Обычно __repr__
используется для отладочного вывода, а __str__
— для пользовательского. Поэтому чтобы вывести именно результат __repr__
, в f-string добавляется флаг !r
:
class User: def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name def __str__(self): return f"{self.first_name} {self.last_name}" def __repr__(self): return f"User's name is: {self.first_name} {self.last_name}" user = User("John", "Doe") print(f"{user}") # John Doe print(f"{user!r}") # User's name is: John Doe
Производительность
Многие удобные “фишки” и синтаксический сахар могут стоить дорого в плане производительности. Однако это не действует на f-string в Python. Посмотрите на скорость выполнения обычного вывода и с использованием f-string:
# python -m timeit -s 'x, y = "Hello", "World"' 'f"{x} {y}"' from string import Template x, y = "Hello", "World" print(f"{x} {y}") # 39.6 наносек за цикл - Быстро! print(x + " " + y) # 43.5 наносек за цикл print(" ".join((x, y))) # 58.1 наносек за цикл print("%s %s" % (x, y)) # 103 наносек за цикл print("{} {}".format(x, y)) # 141 наносек за цикл print(Template("$x $y").substitute(x=x, y=y)) # 1.24 микросекунд за цикл - Медленно!
Все эти форматированные выводы были оценены с помощью timeit
. И можно увидеть, что f-strings самые быстрые в этом списке. Уже ради скорости их можно использовать в своем коде.
Удобство использования
F-strings поддерживают специальный мини-язык для форматированного вывода, который дает возможность выводить так, как считается нужным.
text = "hello world" # Center text: print(f"{text:^15}") # ' hello world ' number = 1234567890 # Set separator print(f"{number:,}") # 1,234,567,890 number = 123 # Add leading zeros print(f"{number:08}") # 00000123
Вложенные f-strings в Python
Интересно, что f-strings можно вкладывать друг в друга:
number = 254.3463 print(f"{f'${number:.3f}':>10s}") # ' $254.346'
Вложенные f-strings можно использовать еще для переменных в качестве модификаторов:
import decimal width = 8 precision = 3 value = decimal.Decimal("42.12345") print(f"output: {value:{width}.{precision}}") # 'output: 42.1'
Форматированный вывод с условием
Вместе с вложенными f-strings можно добавлять условные конструкции:
import decimal value = decimal.Decimal("42.12345") print(f'Result: {value:{"4.3" if value < 100 else "8.3"}}') # Result: 42.1 value = decimal.Decimal("142.12345") print(f'Result: {value:{"4.2" if value < 100 else "8.3"}}') # Result: 142 x = 10 y = 5 print(f"{f'{x = }' if x > 0 else f'{y = }'}") # x = 10
Хотя читаемость такого кода оставляет желать лучше. Такую конструкцию можно использовать для отладки, а потом поменять на более понятный код.
Форматированный вывод лямбда-выражений
Еще в копилку менее читаемого кода является форматированный вывод лямбда-выражений:
print(f"{(lambda x: x**2)(3)}") # 9
Скобки вокруг лямбда-выражения обязательны, иначе двоеточие будет считаться модификатором.
Подготовка данных для Data Mining на Python
Код курса
DPREP
Ближайшая дата курса
по запросу
Продолжительность
32 ак.часов
Стоимость обучения
72 000 руб.
Еще больше подробностей о особенностях программирования на Python вы узнаете на наших образовательных курсах в лицензированном учебном центре обучения и повышения квалификации руководителей и ИТ-специалистов (менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data) в Москве: