Предположим, вам нужно вывести имя и профессию человека. Вы можете написать простую программу следующим образом:
# Define variables name = 'Mark' profession = 'Astronaut' age = 7 # Output info output_string = ('My name is ' + name + ', I am ' + str(age) + ' years old ' + 'and my profession is ' + profession + '.') print(output_string)
My name is Mark, I am 7 years old and my profession is Astronaut.
Но такому подходу не хватает лаконичности и читабельности. К счастью, интерполяция строк предлагает лучшее решение. Она позволяет вставлять переменные, выражения или выходные данные функций непосредственно в строку, делая работу со строками динамичной и устраняя необходимость в ручной конкатенации.
Используя подход с интерполяцией строк, мы могли бы переписать код следующим образом:
# Define variables name = 'Mark' profession = 'Astronaut' age = 7 # Output info output_string = f'My name is {name}, I am {age} years old and my profession is {profession}.' print(output_string)
My name is Mark, I am 7 years old and my profession is Astronaut.
Версия с интерполяцией строк позволяет вставлять выражения непосредственно в строку, не прибегая к беспорядочным конкатенациям. Как видите, это куда более чистый подход.
Содержание
- Базовая интерполяция строк в Python
- Продвинутые техники интерполяции строк в Python
- Плюсы и минусы методов интерполяции строк
- Распространенные проблемы и лучшие практики
- Заключение
Базовая интерполяция строк в Python
В Python существует несколько методов интерполяции строк. Наиболее часто рекомендуемый метод — форматированные строковые литералы, также известные как f-строки, которые стали доступны начиная с Python 3.6.
Другой метод, часто встречающийся в коде старше Python 3.6, — это использование .format()
. Хотя этот метод более многословен, чем f-строки, он иногда имеет свои преимущества (подробности ниже).
Наконец, в легаси-коде можно встретить форматирование в стиле %
.
Использование f-строк (Python 3.6+)
f-строки (форматированные строковые литералы) — это мощный и лаконичный способ форматирования строк в Python. Они обеспечивают удобный и эффективный способ вставки переменных, выражений и вызовов функций непосредственно в строки.
Простой пример базового синтаксиса f-строки:
name = 'Mark' output_string = f'My name is {name}.' print(output_string)
My name is Mark.
В этом коде переменной output_string
присвоена f-строка. Префикс f
перед открывающей кавычкой указывает на то, что строка поддерживает встроенные выражения. Переменная name
оценивается, и ее значение вставляется в строку, в результате чего на выходе получается: «My name is Mark».
В f-строки можно вставлять не только значения переменных, но и вычисления или выражения. Рассмотрим пример.
import math a = 3.0 b = 4.0 # Use string interpolation for the formula print(f'The hypotenuse of a triangle with base {a} and side {b} is {math.sqrt(a ** 2 + b ** 2)}.')
The hypotenuse of a triangle with base 3.0 and side 4.0 is 5.0.
Выражение math.sqrt(a ** 2 + b ** 2)
вычисляется непосредственно в строке, что избавляет от необходимости вычислять значение отдельно перед вставкой в строку.
Использование метода .format()
Как и f-строки, метод .format()
позволяет вставлять в строку переменные и выражения. Базовый синтаксис метода .format()
выглядит следующим образом:
name = 'Mark' output_string = 'My name is {}.'.format(name) print(output_string)
My name is Mark.
Фигурные скобки {}
служат в качестве плейсхолдера, сигнализируя о том, что значение переменной будет вставлено в строку в данной позиции. Конкретное значение переменной, вставляемое в плейсхолдер, определяется аргументом, передаваемым методу .format()
.
Позиционные аргументы
А если вам понадобится несколько плейсхолдеров для нескольких переменных? Рассмотрим следующий код:
name = 'Mark' age = 7 # The placeholders are filled in order of the arguments output_string = 'My name is {} and I am {} years old.'.format(name, age) print(output_string)
My name is Mark and I am 7 years old.
В этом примере нужны две переменные — name
и age
. Следовательно, строка содержит два плейсхолдера, и переменные вставляются в том же порядке, в каком они появляются в методе .format()
. Эти аргументы называются позиционными, поскольку их расположение в строке определяется их позицией в списке аргументов метода.
Индексированные и именованные плейсхолдеры
В качестве вариации идеи плейсхолдера рассмотрим следующий пример:
name = 'Mark' age = 7 # Print age twice output_string = 'My name is {} and I am {} years old. My twin brother is also {} years old.'.format(name, age, age) print(output_string)
My name is Mark and I am 7 years old. My twin brother is also 7 years old.
Здесь мы дважды использовали значение переменной age. Включение одной и той же переменной несколько раз в таком случае выглядит неуклюже и ухудшает читаемость. Можно ли повторно использовать переменную в строке, отформатированной методом .format()
, не повторяя ее? Да: с помощью так называемых индексированных плейсхолдеров.
name = 'Mark' age = 7 # Use indexed placeholders output_string = 'My name is {0} and I am {1} years old. My twin brother is also {1} years old.'.format(name, age) print(output_string)
My name is Mark and I am 7 years old. My twin brother is also 7 years old.
В этом примере мы явно определили порядок переменных в фигурных скобках, придерживаясь нулевой индексации Python. Кроме того, мы повторно использовали переменную с индексом 1 вместо того, чтобы повторять ее.
В качестве альтернативы позиционной индексации можно также использовать именованные аргументы, когда каждому аргументу присваивается имя.
print('My name is {name} and I am {age} years old.'.format(name='Mark', age=7))
My name is Mark and I am 7 years old.
Именованный аргумент оценивается внутри фигурных скобок, в которых указано его имя. В результате плейсхолдер {name}
будет заменен значением «Mark», а плейсхолдер {age}
— значением 7.
Использование оператора %
Последний метод интерполяции строк — оператор %
. Он работает аналогично команде printf()
в C. Его использование устарело и категорически не рекомендуется. Здесь он упомянут, потому что вы можете встретить его в старых кодовых базах.
Основной формат оператора %
таков: "форматируемая строка" % значения
. Форматируемая строка содержит плейсхолдеры (для строк — %s
), которые заменяются значениями. Например, в следующем примере выводится «Hello, Mark».
'Hello, %s' % 'Mark'
'Hello, Mark'
Другие распространенные спецификаторы формата приведены в следующей таблице:
Спецификатор | Значение | Пример |
---|---|---|
%s | Строка | "Hello %s" % "Alice" → "Hello Alice" |
%d | Целое десятичное число | "Age: %d" % 25 → "Age: 25" |
%f | Число с плавающей точкой (по умолчанию 6 знаков после точки) | "Pi: %f" % 3.14159 → "Pi: 3.141590" |
%.nf | Число с плавающей точкой (n знаков после точки) | "%.2f" % 3.14159 → "3.14" |
%x | Шестнадцатеричное число (в нижнем регистре) | "%x" % 255 → "ff" |
%X | Шестнадцатеричное число (в верхнем регистре) | "%X" % 255 → "FF" |
%o | Восьмеричное число | "%o" % 255 → "377" |
Оператор %
имеет множество ограничений. Например, он менее читабелен, чем f-строки. Обратите внимание на следующий код:
name = "Alice" age = 30 height = 5.6 # The % operator is hard to scan message = "My name is %s, I am %d years old, and my height is %.1f feet." % (name, age, height) print(message)
My name is Alice, I am 30 years old, and my height is 5.6 feet.
Понятен ли вам этот код с первого взгляда? Скорее всего, нет. Вам придется бегать глазами от плейсхолдеров к переменным и обратно. При этом будет легко запутаться.
Теперь рассмотрим эквивалентный код с использованием f-строк.
# This is much cleaner message = f"My name is {name}, I am {age} years old, and my height is {height:.1f} feet." print(message)
My name is Alice, I am 30 years old, and my height is 5.6 feet.
Код чист, понятен и прост в написании.
Продвинутые техники интерполяции строк в Python
Теперь, когда мы разобрались с основами интерполяции строк в Python, давайте рассмотрим некоторые более продвинутые варианты ее использования.
Интерполяция многострочных строк
F-строки также можно использовать для многострочного содержимого. Для этого применяется f
с тройными кавычками (одинарными или двойными). Текст можно писать в нескольких строках, а в выводе он появится в точно таком же виде.
name = 'Mark' profession = 'Astronaut' age = 7 # This is an example of a multiline string bio = f""" Name: {name} Profession: {profession} Age: {age} """ print(bio)
Name: Mark Profession: Astronaut Age: 7
Многострочные строки также можно создавать с помощью метода .format()
.
name = 'Mark' profession = 'Astronaut' age = 7 # This is a multiline string with .format() bio = """ Name: {} Profession: {} Age: {} """.format(name, profession, age) print(bio)
Name: Mark Profession: Astronaut Age: 7
Варианты использования интерполяции многострочных строк
Зачем нужна интерполяция многострочных строк? Вот несколько примеров ее использования:
- Генерация многострочных электронных писем или сообщений
- Ведение логов и отладка
- Динамическая генерация SQL-запросов
Генерация многострочных электронных писем или сообщений
Предположим, вы рассылаете шаблонные письма многим приглашенным на техническую конференцию.
name = "Alice" event = "Annual Tech Conference" date = "March 15, 2025" email = """Dear {name}, We are pleased to invite you to the {event} taking place on {date}. We hope you can join us for an exciting experience. Best regards, The Event Team""".format(name=name, event=event, date=date) print(email)
Dear Alice, We are pleased to invite you to the Annual Tech Conference taking place on March 15, 2025. We hope you can join us for an exciting experience. Best regards, The Event Team
С помощью f-строк создать такие письма просто и эффективно. Чтобы изменить имя, событие или дату, просто поменяйте их в переменных, и строка изменится автоматически.
Ведение логов и отладка
Многострочные строки полезны для вывода сообщений об ошибках в логах.
error_code = 404 url = '/missing-page' timestamp = '2025-02-05 12:30:00' error_message = 'The requested page could not be found.' log_message = f"""[ERROR {error_code}] Time: {timestamp} URL: {url} {error_message}""" print(log_message)
[ERROR 404] Time: 2025-02-05 12:30:00 URL: /missing-page The requested page could not be found.
Этот метод позволяет структурировать сообщения и облегчает отладку с помощью правильно оформленных логов.
Динамическая генерация SQL-запросов
SQL-запросы можно создавать динамически с помощью многострочных строк.
table = 'users' column = 'email' value = 'alice@example.com' query = f"""SELECT * FROM {table} WHERE {column} = '{value}';""" print(query)
SELECT * FROM users WHERE email = 'alice@example.com';
Этот метод делает SQL-запросы читабельными и сохраняет отступы. Кроме того, он избавляет от необходимости использовать +
для конкатенации строк.
Другие примеры использования интерполяции многострочных строк:
- Написание форматированных контрактов
- Создание документов в формате Markdown или $\LaTeX$
- Создание многострочных шаблонов HTML/XML
- Генерация ответов API или JSON-подобного текста
Преимущества интерполяции многострочных строк
Как мы видим, у интерполяции многострочных строк есть несколько преимуществ:
- Сохранение форматирования без использования символа \n.
- Улучшение читаемости по сравнению с однострочным форматированием.
- Уменьшение беспорядка при работе со структурированным текстом (например, логами, запросами, отчетами).
- Возможность динамически генерировать текст без нарушения отступов.
Форматирование чисел и специальных значений
Чтобы управлять количеством отображаемых десятичных знаков с помощью f-строки, используйте синтаксис f'{value:.nf}'
, где value
— число с плавающей точкой, n
— количество десятичных знаков, а f
(после .
) обозначает форматирование float.
В качестве примера давайте рассмотрим код, который выводит число пи с разным количеством знаков после точки.
pi = 3.1415926535 print(f'Pi rounded to 2 decimal places: {pi:.2f}') print(f'Pi rounded to 4 decimal places: {pi:.4f}') print(f'Pi rounded to 0 decimal places: {pi:.0f}')
Pi rounded to 2 decimal places: 3.14 Pi rounded to 4 decimal places: 3.1416 Pi rounded to 0 decimal places: 3
Форматирование с помощью метода .format()
аналогично:
print('Pi rounded to 2 decimal places: {:.2f}'.format(pi)) print('Pi rounded to 4 decimal places: {:.4f}'.format(pi)) print('Pi rounded to 0 decimal places: {:.0f}'.format(pi))
Pi rounded to 2 decimal places: 3.14 Pi rounded to 4 decimal places: 3.1416 Pi rounded to 0 decimal places: 3
Вы можете использовать f-строку для форматирования процентов, используя синтаксис :.n%
, где n
— количество десятичных знаков.
score = 0.875 print(f"Success rate: {score:.2%}")
Success rate: 87.50%
С помощью f-строк можно форматировать и валюту, используя :,
для разделения тысяч и .nf
для управления десятичными знаками. Вы также можете включить символ валюты, например $, € или £, непосредственно в строку.
amount = 98765.4321 print(f"USD: ${amount:,.2f}") print(f"EUR: €{amount:,.2f}") print(f"GBP: £{amount:,.2f}")
USD: $98,765.43 EUR: €98,765.43 GBP: £98,765.43
Использование f-строк со словарями и списками
Чтобы использовать f-строки со словарем в Python, можно использовать квадратные скобки внутри фигурных скобок: {dict['key']}
.
person = { 'name': 'Alice', 'age': 30, 'city': 'New York' } print(f"My name is {person['name']}, I am {person['age']} years old, and I live in {person['city']}.")
My name is Alice, I am 30 years old, and I live in New York.
Вместо того чтобы обращаться к каждому ключу вручную, можно распаковать словарь в f-строку следующим образом:
person = { 'name': 'Alice', 'age': 30, } print(f'My name is {name} and I am {age} years old.'.format(**person))
My name is Alice and I am 7 years old.
Чтобы избежать ошибки, связанной с отсутствием ключей, используйте get()
для доступа к словарю.
person = {"name": "Alice"} # Error: key 'city' is missing print(f"City: {person['city']}")
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) Cell In[87], line 4 1 person = {"name": "Alice"} 3 # Error: key 'city' is missing ----> 4 print(f"City: {person['city']}") KeyError: 'city'
print(f"City: {person.get('city', 'Not specified')}")
City: Not specified
Плюсы и минусы методов интерполяции строк
Как вы уже поняли, f-строки и метод .format()
являются полезными методами интерполяции строк. Давайте сравним их.
Функционал | f-строки | .format() | %-форматирование |
---|---|---|---|
Читаемость | 🟢 Лучше всего | 🟡 ОК | 🔴 Хуже всего |
Производительность | 🟢 Выше всего | 🟡 Меньше | 🔴 Ниже всего |
Поддержка выражений | 🟢 Есть | 🟡 Косвенная | 🔴 Нет |
Поддержка многострочных строк | 🟢 Есть | 🟢 Есть | 🔴 Нет |
Простота использования | 🟢 Выше всего | 🟡 Средняя | 🔴 Ниже всего |
Отладка (оператор = ) | 🟢 Есть (Python 3.8+) | 🔴 Нет | 🔴 Нет |
Когда следует использовать .format(), а не f-строки?
Преимущество | Почему стоит использовать .format()? |
---|---|
Поддержка легаси-кода | Работает в Python 2.7+ |
Гибкий порядок | Позволяет легко менять местами плейсхолдеры |
Динамическое форматирование | Работает, если спецификатор формата динамический |
Лучшая обработка фигурных скобок | Позволяет обойтись без дополнительного ручного экранирования |
Работа со словарями | Проще использовать ключи словарей |
Распространенные проблемы и лучшие практики
Ниже приведены методы устранения неполадок и советы по использованию интерполяции строк в Python.
Синтаксические ошибки, связанные с фигурными скобками
Применяя интерполяцию строк с использованием фигурных скобок, можно допустить много ошибок.
1. Следите за тем, чтобы каждая скобка имела пару.
print('Hello, my name is {name!'}
Cell In[96], line 1 print('Hello, my name is {name!'} ^ SyntaxError: closing parenthesis '}' does not match opening parenthesis '('
К счастью, эта ошибка простая, и исправить ее легко.
2. Используйте {{
и }}
для отображения литерала {}
.
Что произойдет, если вы захотите вывести фигурные скобки внутри интерполированной строки? Все, что находится внутри фигурных скобок, будет оцениваться.
print(f'Set notation: {a, b, c}')
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[101], line 1 ----> 1 print(f'Set notation: {a, b, c}') NameError: name 'c' is not defined
Python интерпретирует a, b, c
внутри фигурных скобок как кортеж, пытаясь найти значение, связанное с a
. Поскольку такой переменной не существует, возникает ошибка KeyError. Чтобы это исправить, нужно использовать двойные фигурные скобки {{}}
.
print(f'Set notation: {{a, b, c}}')
Set notation: {a, b, c}
Сравнение производительности f-строк и .format()
Давайте сравним производительность f-строк и .format()
.
import timeit name = "Alice" age = 30 pi = 3.1415926535 # Measure f-string performance f_string_time = timeit.timeit('f"My name is {name} and I am {age} years old."', globals=globals(), number=1000000) # Measure .format() performance format_time = timeit.timeit('"My name is {} and I am {} years old.".format(name, age)', globals=globals(), number=1000000) # Measure f-string performance with expressions f_string_expr_time = timeit.timeit('f"Pi rounded to 2 decimal places: {pi:.2f}"', globals=globals(), number=1000000) # Measure .format() performance with expressions format_expr_time = timeit.timeit('"Pi rounded to 2 decimal places: {:.2f}".format(pi)', globals=globals(), number=1000000) # Print results print(f"f-string (simple): {f_string_time:.6f} seconds") print(f".format() (simple): {format_time:.6f} seconds") print(f"f-string (with expression): {f_string_expr_time:.6f} seconds") print(f".format() (with expression): {format_expr_time:.6f} seconds")
f-string (simple): 0.080447 seconds .format() (simple): 0.129860 seconds f-string (with expression): 0.123171 seconds .format() (with expression): 0.146242 seconds
Как видите, с точки зрения эффективности лучше предпочесть f-строки.
Лучшие практики для чистой и читабельной интерполяции строк
Чтобы форматирование строк было понятным, эффективным и удобным, следуйте этим лучшим практикам.
1. Для удобочитаемости отдавайте предпочтение f-строкам (Python 3.6+)
# Recommended name = "Alice" age = 30 print(f"My name is {name} and I am {age} years old.") # Not Recommended (Less readable) print("My name is {} and I am {} years old.".format(name, age)) # Avoid using % formatting (Outdated) print("My name is %s and I am %d years old." % (name, age))
My name is Alice and I am 30 years old. My name is Alice and I am 30 years old. My name is Alice and I am 30 years old.
2. Используйте именованные плейсхолдеры для ясности.
# Named placeholders (readable) user = {"name": "Alice", "age": 30} print(f"My name is {user['name']} and I am {user['age']} years old.") # Using indexes in .format() (not as readable) print("My name is {0} and I am {1} years old.".format("Alice", 30))
My name is Alice and I am 30 years old. My name is Alice and I am 30 years old.
3. Следите за тем, чтобы многострочные строки были удобочитаемыми.
name = "Alice" age = 30 message = f"""Hello, {name}! We are happy to invite you to our event. At {age} years old, you are eligible for the VIP pass. Best regards, Event Team """ print(message)
Hello, Alice! We are happy to invite you to our event. At 30 years old, you are eligible for the VIP pass. Best regards, Event Team
4. Для лучшей отладки используйте в логах f-строки.
value = 42 # Output: value = 42 print(f"{value = }")
value = 42
Python 3.8 и более поздние версии поддерживают =
для отладки в f-строках.
Заключение
Интерполяция строк — это мощная функция Python, которая делает форматирование строк чище, читабельнее и эффективнее. Среди доступных методов f-строки — наиболее современный и рекомендуемый подход. Он предлагает лучшую производительность, ясность и гибкость по сравнению со старыми методами, такими как .format()
и %
-форматирование.
Следуя лучшим практикам, таким как использование именованных плейсхолдеров, контроль точности десятичных дробей, выравнивание текста для удобства чтения и обработка отсутствующих ключей словаря, вы обеспечите чистое, профессиональное и удобное форматирование строк.
Перевод статьи “Python String Interpolation: A Beginner’s Guide”.