- f-строки в Python
- 5 способов форматирования строк
- Курс по языку Python 3
- Погружение в f-строки
- Производительность
- Заключение
- F-строки в Python мощнее, чем можно подумать
- Форматирование даты и времени
- Имена переменных и отладка
- Методы __repr__ и __str__
- Отличная производительность
- Вся сила мини-языка спецификаций форматирования
- Вложенные f-строки
- Условное форматирование
- Лямбда-выражения
- Итоги
f-строки в Python
Начиная с версии 3.6 в Python появился новый тип строк — f-строки, которые буквально означают «formatted string». Эти строки улучшают читаемость кода, а также работают быстрее чем другие способы форматирования. F-строки задаются с помощью литерала «f» перед кавычками.
f-строки — это пятый способ (sic!) форматирования строк в Python, который очень похож на использование метода format().
Вспомним все 5 способов форматирования.
5 способов форматирования строк
1. Конкатенация. Грубый способ форматирования, в котором мы просто склеиваем несколько строк с помощью операции сложения:
>>> name = "Дмитрий" >>> age = 25 >>> print("Меня зовут " + name + ". Мне " + str(age) + " лет.") >>> Меня зовут Дмитрий. Мне 25 лет.
2. %-форматирование. Самый популярный способ, который перешел в Python из языка С. Передавать значения в строку можно через списки и кортежи , а также и с помощью словаря. Во втором случае значения помещаются не по позиции, а в соответствии с именами.
>>> name = "Дмитрий" >>> age = 25 >>> print("Меня зовут %s. Мне %d лет." % (name, age)) >>> Меня зовут Дмитрий. Мне 25 лет. >>> print("Меня зовут %(name)s. Мне %(age)d лет." % ) >>> Меня зовут Дмитрий. Мне 25 лет.
3. Template-строки. Этот способ появился в Python 2.4, как замена %-форматированию ( PEP 292 ), но популярным так и не стал. Поддерживает передачу значений по имени и использует $-синтаксис как в PHP.
>>> from string import Template >>> name = "Дмитрий" >>> age = 25 >>> s = Template('Меня зовут $name. Мне $age лет.') >>> print(s.substitute(name=name, age=age)) >>> Меня зовут Дмитрий. Мне 25 лет.
4. Форматирование с помощью метода format(). Этот способ появился в Python 3 в качестве замены %-форматированию. Он также поддерживает передачу значений по позиции и по имени.
>>> name = "Дмитрий" >>> age = 25 >>> print("Меня зовут <>. Мне <> лет.".format(name, age) >>> Меня зовут Дмитрий. Мне 25 лет. >>> print("Меня зовут Мне лет.".format(age=age, name=name) >>> Меня зовут Дмитрий. Мне 25 лет.
5. f-строки. Форматирование, которое появилось в Python 3.6 ( PEP 498 ). Этот способ похож на форматирование с помощью метода format(), но гибче, читабельней и быстрей.
>>> name = "Дмитрий" >>> age = 25 >>> print(f"Меня зовут Мне лет.") >>> Меня зовут Дмитрий. Мне 25 лет.
Курс по языку Python 3
- Научитесь программировать на Python с нуля
- Более 130 уроков и 300 заданий
- Поддержка преподавателя на всех этапах
Погружение в f-строки
f-строки делают очень простую вещь — они берут значения переменных, которые есть в текущей области видимости, и подставляют их в строку. В самой строке вам лишь нужно указать имя этой переменной в фигурных скобках.
>>> name = "Дмитрий" >>> age = 25 >>> print(f"Меня зовут Мне лет.") >>> Меня зовут Дмитрий. Мне 25 лет.
f-строки также поддерживают расширенное форматирование чисел:
>>> from math import pi >>> print(f"Значение числа pi: ") >>> Значение числа pi: 3.14
С помощью f-строк можно форматировать дату без вызова метода strftime():
>>> from datetime import datetime as dt >>> now = dt.now() >>> print(f"Текущее время ") >>> Текущее время 24.02.2017 15:51
Они поддерживают базовые арифметические операции. Да, прямо в строках:
>>> x = 10 >>> y = 5 >>> print(f" x / 2 = ") >>> 10 x 5 / 2 = 25.0
Позволяют обращаться к значениям списков по индексу:
>>> planets = ["Меркурий", "Венера", "Земля", "Марс"] >>> print(f"Мы живим не планете ") >>> Мы живим не планете Земля
А также к элементам словаря по ключу:
>>> planet = >>> print(f"Планета . Радиус км.") >>> Планета Земля. Радиус 6378.0 км.
Причем вы можете использовать как строковые, так и числовые ключи. Точно так же, как в обычном Python коде:
>>> digits = >>> print(f"0 - , 1 - ") >>> 0 - ноль, 1 - один
Вы можете вызывать в f-строках методы объектов:
>>> name = "Дмитрий" >>> print(f"Имя: ") >>> Имя: ДМИТИРИЙ
f-строки очень гибкий и мощный инструмент для создания самых разнообразных шаблонов.
Со всеми возможностями f-строк вы можете ознакомиться в PEP498.
Производительность
F-строки не только гибкие, но и быстрые. И для сравнения производительности разных подходов к форматированию я подготовил два шаблона:
- простой, в который нужно вставить всего два значения: строку и число;
- сложный, данные для которого собираются из разных переменных, а внутри происходит преобразование даты, вещественного числа, а также округление.
Финальная простая строка получается такой:
Сложная строка на выходе такая:
Сегодня 24.02.2017.
Мы живём на планете Земля. Её радиус 6378 км., а масса 5.973e+24
Период обращения планеты вокруг Солнца 365 дней.
Далее я написал 5 функций, каждая из которых возвращает строку отформатированную одним из способом, а после запустил каждую функцию много раз. Пример всех функций и тестового скрипта можете скачать тут.
После недолгого тестирования я получил следующие результаты:
На простых примерах f-строки показывают наилучшие результаты.
На 25% быстрее %-форматирования и метода format().
На сложных шаблонах f-строки ведут себя так же как %-форматирование
(разница в пользу %-форматирования не превышает величину погрешности).
А вот относительно метода format() f-строки быстрее на 27%.
Заключение
Если вы используете Python 3.6 и старше, то самое время использовать f-строки — они гибкие и быстрые.
F-строки в Python мощнее, чем можно подумать
Форматированные строковые литералы, которые ещё называют f-строками (f-strings), появились довольно давно, в Python 3.6. Поэтому все знают о том, что это такое, и о том, как ими пользоваться. Правда, f-строки обладают кое-какими полезными возможностями, некоторыми особенностями, о которых кто-нибудь может и не знать. Разберёмся с некоторыми интересными возможностями f-строк, которые могут оказаться очень кстати в повседневной работе Python-программиста.
Форматирование даты и времени
Форматирование чисел средствами f-строк — это обычное дело. А вы знали, что с их помощью можно ещё форматировать значения, представляющие даты и временные метки?
import datetime today = datetime.datetime.today() print(f"") # 2022-03-11 print(f"") # 2022
С помощью f-строк можно форматировать дату и время так, как если бы для этого использовался бы метод datetime.strftime . Это особенно приятно, когда понимаешь, что тут имеется больше возможностей форматирования значений, чем те немногие, которые упомянуты в документации. Так, Python-метод strftime поддерживает, кроме прочего, все способы форматирования значений, поддерживаемые его базовой реализацией на C. Эти возможности могут зависеть от платформы, именно поэтому в документации они не упоминаются. Но получается, что этими возможностями по форматированию значений, всё равно, можно воспользоваться. Например, можно применить спецификатор формата %F , являющийся эквивалентом %Y-%m-%d , или спецификатор %T , аналогичный %H:%M:%S . Стоит ещё упомянуть и о спецификаторах формата %x и %X , представляющих собой, соответственно, принятые в используемом языковом стандарте способы представления даты и времени. Использование этих возможностей форматирования значений, конечно, не ограничивается только f-строками. Полный список спецификаторов формата даты и времени можно найти в Linux-справке по strftime.
Имена переменных и отладка
Функционал f-строк сравнительно недавно (начиная с Python 3.8) дополнен возможностями по выводу имён переменных вместе с их значениями:
x = 10 y = 25 print(f"x = , y = ") # x = 10, y = 25 print(f", ") # Лучше! (3.8+) # x = 10, y = 25 print(f"") # x = 10.000
Эта возможность называется «отладкой» («debugging»), её можно применять вместе с другими модификаторами. Она, кроме того, сохраняет пробелы, поэтому при обработке конструкций вида f»» и f»» получатся разные строки.
Методы __repr__ и __str__
Для формирования строковых представлений экземпляров классов по умолчанию используется метод __str__ . Но если вместо этого метода нужно применить метод __repr__ — можно воспользоваться флагом преобразования !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" " def __repr__(self): return f"User's name is: " user = User("John", "Doe") print(f"") # John Doe print(f"") # User's name is: John Doe
Тут, внутри f-строки, можно было бы просто вызвать repr(some_var) , но использование флага преобразования — это образец приятного стандартного и краткого решения подобной задачи.
Отличная производительность
За некие мощные возможности чего-либо и за «синтаксический сахар» часто приходится платить производительностью. Но в случае с f-строками это не так:
# python -m timeit -s 'x, y = "Hello", "World"' 'f" "' from string import Template x, y = "Hello", "World" print(f" ") # 39.6 nsec per loop - Быстро! print(x + " " + y) # 43.5 nsec per loop print(" ".join((x, y))) # 58.1 nsec per loop print("%s %s" % (x, y)) # 103 nsec per loop print("<> <>".format(x, y)) # 141 nsec per loop print(Template("$x $y").substitute(x=x, y=y)) # 1.24 usec per loop - Медленно!
Вышеприведённый код протестирован с помощью модуля timeit ( python -m timeit -s ‘x, y = «Hello», «World»’ ‘f» »’ ). Как видите, f-строки оказались самым быстрым из всех механизмов форматирования данных, которые даёт нам Python. Поэтому, даже если вы предпочитаете пользоваться другими средствами форматирования строк, рассмотреть возможность перехода на f-строки стоит хотя бы ради повышения производительности.
Вся сила мини-языка спецификаций форматирования
F-строки поддерживают мини-язык спецификаций форматирования Python. Поэтому в модификаторы, используемые в f-строках, можно внедрить множество операций форматирования данных:
text = "hello world" # Центрирование текста: print(f"") # ' hello world ' number = 1234567890 # Установка разделителя групп разрядов print(f"") # 1,234,567,890 number = 123 # Добавление начальных нулей print(f"") # 00000123
Мини-язык форматирования Python включает в себя гораздо больше, чем конструкции, рассчитанные на форматирование чисел и дат. Этот язык, кроме прочего, позволяет выравнивать или центрировать текст, добавлять к строкам начальные нули или пробелы, задавать разделители групп разрядов. Всем этим, конечно, можно пользоваться не только в f-строках, но и при применении других способов форматирования данных.
Вложенные f-строки
Если чьи-то нужды по форматированию данных не удаётся удовлетворить с помощью простых f-строк, можно прибегнуть к f-строкам, вложенным друг в друга:
number = 254.3463 print(f"':>10s>") # ' $254.346'
Одни f-строки можно встраивать в другие f-строки, поступая так ради решения хитрых задач форматирования данных. Например — чтобы, как показано выше, добавить знак доллара к числу с плавающей точкой, выровненному по правому краю.
Вложенные f-строки могут применяться и в тех случаях, когда в спецификаторах формата нужно использовать переменные. Это, кроме прочего, способно улучшить читабельность кода с f-строками:
import decimal width = 8 precision = 3 value = decimal.Decimal("42.12345") print(f"output: .>") # 'output: 42.1'
Условное форматирование
Взяв за основу предыдущий пример с вложенными f-строками, можно пойти немного дальше и воспользоваться во внутренних f-строках тернарными условными операторами:
import decimal value = decimal.Decimal("42.12345") print(f'Result: >') # Result: 42.1 value = decimal.Decimal("142.12345") print(f'Result: >') # Result: 142
Подобные конструкции могут очень быстро стать нечитабельными. Поэтому, пользуясь ими, возможно, есть смысл разделять их на несколько строк кода.
Лямбда-выражения
Тот, кто хочет расширить границы возможностей f-строк, попутно взбесив тех, кто будет читать его код, может, приложив некоторые усилия, воспользоваться лямбда-выражениями:
Скобки вокруг лямбда-выражения в данном случае обязательны. Это так из-за двоеточия, ( : ), которое, в противном случае, будет восприниматься системой как часть f-строки.
Итоги
Как видите, f-строки — это, и правда, весьма мощный механизм. Они обладают гораздо большими возможностями, чем думает большинство программистов. Основная часть этих «неизвестных» возможностей, правда, описана в документации по Python. Поэтому рекомендую читать документацию, причём — не только по f-строкам, но и по другим используемым вами модулям или возможностям Python. Углубление в документацию часто помогает обнаружить какие-то очень полезные вещи, которые не найти даже зарывшись в Stack Overflow.
О, а приходите к нам работать? 🤗 💰
Мы в wunderfund.io занимаемся высокочастотной алготорговлей с 2014 года. Высокочастотная торговля — это непрерывное соревнование лучших программистов и математиков всего мира. Присоединившись к нам, вы станете частью этой увлекательной схватки.
Мы предлагаем интересные и сложные задачи по анализу данных и low latency разработке для увлеченных исследователей и программистов. Гибкий график и никакой бюрократии, решения быстро принимаются и воплощаются в жизнь.
Сейчас мы ищем плюсовиков, питонистов, дата-инженеров и мл-рисерчеров.