F-строки Python 3: улучшенный синтаксис форматирования строк

Spread the love

Начиная с Python 3.6, f-строки – отличный новый способ форматирования строк. Это способ не только более читабелен, более краток и менее подвержен ошибкам, чем другие способы форматирования, но и быстрее всех других!

К концу этой статьи вы узнаете, как и почему нужно использовать f-строки.

Но сначала, рассмотрим старые варианты вывода строк.

“Старая-школа” форматирования строк в Python

До Python 3.6 у нас было два основных способа встраивания выражений Python в строковые литералы для форматирования: % – форматирование и str.format(). Рассмотрим, как их использовать и каковы их ограничения.

Вариант #1: % – форматирование

Этот способ форматирования Python существует в языке с самого его начала. Вы можете прочитать о нем больше информации в документации по Python. Имейте в виду, что % – форматирование не рекомендуется к использованию:

Операции форматирования, описанные здесь, демонстрируют различные проблемы, которые приводят к ряду распространенных ошибок (таких как неправильное отображение кортежей и словарей).
Использование более новых форматированных строковых литералов или интерфейса str.format() помогает избежать этих ошибок. Эти альтернативы также предоставляют более мощные, гибкие и расширяемые подходы к форматированию текста. (Источник)

Как используется % – форматирование

Строковые объекты имеют встроенную операцию с использованием оператора %, который можно использовать для форматирования строк. Вот как это выглядит на практике:

>>> name = "Eric"
>>> "Hello, %s." % name
'Hello, Eric.'

Чтобы вставить более одной переменной, вы должны использовать кортеж из этих переменных.

>>> name = "Eric"
>>> age = 74
>>> "Hello, %s. You are %s." % (name, age)
'Hello Eric. You are 74.'

Недостатки % – форматирования

Примеры кода, которые вы только что видели выше, достаточно читабельны. Однако, как только вы начнете использовать несколько параметров и более длинные строки, ваш код быстро станет менее читаемым. Все начинает выглядеть немного грязно:

>>> first_name = "Eric"
>>> last_name = "Idle"
>>> age = 74
>>> profession = "comedian"
>>> affiliation = "Monty Python"
>>> "Hello, %s %s. You are %s. You are a %s. You were a member of %s." % (first_name, last_name, age, profession, affiliation)
'Hello, Eric Idle. You are 74. You are a comedian. You were a member of Monty Python.'

К сожалению, этот вид форматирования не очень хорош, потому что он многословен и приводит к ошибкам, таким как неправильное отображение кортежей или словарей. К счастью, есть альтернативы.

Вариант #2: str.format()

Этот новый способ вывода строк был представлен в Python 2.6. Вы можете обратиться к документации Python для получения дополнительной информации.

Как используется str.format()

str.format() – это улучшение % – форматирования. Он использует обычный синтаксис вызова функции и расширяется с помощью метода __format__() для объекта, преобразуемого в строку.

С помощью str.format() поля вывода переменных отмечены фигурными скобками:

>>> "Hello, {}. You are {}.".format(name, age)
'Hello, Eric. You are 74.'

Вы можете ссылаться на переменные в любом порядке, ссылаясь по их индексам:

>>> "Hello, {1}. You are {0}.".format(age, name)
'Hello, Eric. You are 74.'

Но если вы вставите имена переменных, вы получите дополнительную возможность передавать объекты, а затем ссылаться на параметры и методы между фигурными скобками:

>>> person = {'name': 'Eric', 'age': 74}
>>> "Hello, {name}. You are {age}.".format(name=person['name'], age=person['age'])
'Hello, Eric. You are 74.'

Вы также можете использовать символ **, чтобы использовать этот трек со словарями:

>>> person = {'name': 'Eric', 'age': 74}
>>> "Hello, {name}. You are {age}.".format(**person)
'Hello, Eric. You are 74.'

str.format() определенно является улучшением по сравнению с % – форматированием, но и у него есть свои недостатки.

В чем недостатки str.format()

Код, использующий str.format(), гораздо легче читается, чем код, использующий % -форматирование, но str.format() все еще может быть достаточно многословным, когда вы имеете дело с несколькими параметрами и более длинными строками. Посмотрите на это:

>>> first_name = "Eric"
>>> last_name = "Idle"
>>> age = 74
>>> profession = "comedian"
>>> affiliation = "Monty Python"
>>> print(("Hello, {first_name} {last_name}. You are {age}. " + 
>>>        "You are a {profession}. You were a member of {affiliation}.") \
>>>        .format(first_name=first_name, last_name=last_name, age=age, \
>>>                profession=profession, affiliation=affiliation))
'Hello, Eric Idle. You are 74. You are a comedian. You were a member of Monty Python.'

Если у вас есть переменные, которые вы хотите передать в .format() в словаре, то вы можете просто распаковать его с помощью .format (** some_dict) и ссылаться на значения по ключу в строке.

f-Строки: новый и улучшенный способ форматирования строк в Python

f-строки были представлены в Python 3.6. Вы можете прочитать об этом в PEP 498, который был написан Эриком В. Смитом в августе 2015 года.

Также называемые “formatted string literals”(“отформатированные строковые литералы”), f-строки – это строковые литералы, которые имеют f в начале и фигурные скобки, содержащие выражения, которые будут заменены их значениями. Выражения оцениваются во время выполнения, а затем форматируются с использованием протокола format. Как всегда, документация Python – ваш друг, когда вы хотите получить больше информации.

Вот несколько способов, которыми f-строки могут сделать вашу жизнь проще.

Простой синтаксис

Синтаксис похож на тот, который вы использовали с str.format(), но менее подробный. Посмотрите, насколько легко это читается:

>>> name = "Eric"
>>> age = 74
>>> f"Hello, {name}. You are {age}."
'Hello, Eric. You are 74.'

Также было бы правильно использовать заглавную букву F:

>>> F"Hello, {name}. You are {age}."
'Hello, Eric. You are 74.'

Ты еще не любишь f – строки? Я надеюсь, что к концу этой статьи вы ответите >>> F"Yes!"

Произвольные выражения

Поскольку f-строки оцениваются во время выполнения, вы можете поместить в них все допустимые выражения Python. Это позволяет вам делать некоторые изящные вещи.

Вы можете сделать что-то довольно простое, как это:

>>> f"{2 * 37}"
'74'

Но вы также можете вызывать функции. Вот пример:

>>> def to_lowercase(input):
...     return input.lower()

>>> name = "Eric Idle"
>>> f"{to_lowercase(name)} is funny."
'eric idle is funny.'

Вы также можете напрямую вызвать метод:

>>> f"{name.lower()} is funny."
'eric idle is funny.'

Вы даже можете использовать объекты, созданные из классов с f-строками. Представьте, что у вас есть следующий класс:

class Comedian:
    def __init__(self, first_name, last_name, age):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age

    def __str__(self):
        return f"{self.first_name} {self.last_name} is {self.age}."

    def __repr__(self):
        return f"{self.first_name} {self.last_name} is {self.age}. Surprise!"

Вы сможете сделать это:

>>> new_comedian = Comedian("Eric", "Idle", "74")
>>> f"{new_comedian}"
'Eric Idle is 74.'

Методы __str__() и __repr__() имеют дело с тем, как объекты представляются в виде строк, поэтому вам необходимо убедиться, что вы включили хотя бы один из этих методов в определение класса. Если вам нужно выбрать один, используйте __repr__(), поскольку его можно использовать вместо __str__().

Строка, возвращаемая __str__(), является неформальным строковым представлением объекта и должна быть читабельной. Строка, возвращаемая __repr__(), является официальным представлением и должна быть однозначной. Вызов str() и repr() предпочтительнее прямого использования __str__ () и __repr__().

По умолчанию f-строки будут использовать __str__(), но вы можете убедиться, что они используют __repr__(), если вы включите флаг преобразования !r:

>>> f"{new_comedian}"
'Eric Idle is 74.'
>>> f"{new_comedian!r}"
'Eric Idle is 74. Surprise!'

Если вы хотите прочитать больше, о f-строк которые поддерживают полные выражения Python, вы можете сделать это здесь.

Многострочные f-строки

Вы можете использовать многострочные строки:

>>> name = "Eric"
>>> profession = "comedian"
>>> affiliation = "Monty Python"
>>> message = (
...     f"Hi {name}. "
...     f"You are a {profession}. "
...     f"You were in {affiliation}."
... )
>>> message
'Hi Eric. You are a comedian. You were in Monty Python.'

Но помните, что вам нужно поместить «f» перед каждой строкой многострочной строки. Следующий код не будет работать:

>>> message = (
...     f"Hi {name}. "
...     "You are a {profession}. "
...     "You were in {affiliation}."
... )
>>> message
'Hi Eric. You are a {profession}. You were in {affiliation}.'

Если вы хотите распределить строки по нескольким строкам, вы можете так же сделать это с помощью \:

>>> message = f"Hi {name}. " \
...           f"You are a {profession}. " \
...           f"You were in {affiliation}."
...
>>> message
'Hi Eric. You are a comedian. You were in Monty Python.'

Или с помощью “””:

>>> message = f"""
...     Hi {name}. 
...     You are a {profession}. 
...     You were in {affiliation}.
... """
...
>>> message
'\n    Hi Eric.\n    You are a comedian.\n    You were in Monty Python.\n'

Скорость

Символ f в f – строках также может означать «быстро» (fast).

f-строки быстрее, чем % – форматирование и str.format(). Как вы уже видели, f-строки – это выражения, вычисляемые во время выполнения, а не постоянные значения. Вот выдержка из документов:

«f-строки обеспечивают способ встраивания выражений в строковые литералы, используя минимальный синтаксис. Следует отметить, что f-строка на самом деле является выражением, вычисляемым во время выполнения, а не постоянным значением. В исходном коде Python f-строка является литеральной строкой с префиксом f, которая содержит выражения внутри фигурных скобок. Выражения заменяются их значениями ». (Источник)

Во время выполнения выражение внутри фигурных скобок оценивается в собственной области видимости и затем помещается вместе со строковым литералом в часть f-строки. Полученная строка затем возвращается. Это все, что нужно.

Вот сравнение скорости:

>>> import timeit
>>> timeit.timeit("""name = "Eric"
... age = 74
... '%s is %s.' % (name, age)""", number = 10000)
0.003324444866599663

>>> timeit.timeit("""name = "Eric"
... age = 74
... '{} is {}.'.format(name, age)""", number = 10000)
0.004242089427570761
>>> timeit.timeit("""name = "Eric"
... age = 74
... f'{name} is {age}.'""", number = 10000)
0.0024820892040722242

Как вы можете видеть, f-строки выходят на первое место.

Тем не менее, это не всегда так. Когда они были впервые реализованы, у них были некоторые проблемы со скоростью, и их нужно было делать быстрее, чем str.format(). Был введен специальный код BUILD_STRING.

Python f-строки: особенности использования

Теперь, когда вы узнали все о том, почему f-строки великолепны, я уверен, что вы захотите начать их использовать. Вот несколько деталей, о которых нужно помнить, когда вы отправляетесь в этот дивный новый мир.

Кавычки

Вы можете использовать различные типы кавычек внутри выражений. Просто убедитесь, что вы не используете кавычки того же типа на внешней стороне f-строки, которые вы используете в выражении.

Этот код будет работать:

>>> f"{'Eric Idle'}"
'Eric Idle'

Этот код также будет работать:

>>> f'{"Eric Idle"}'
'Eric Idle'

Вы также можете использовать тройные кавычки:

>>> f"""Eric Idle"""
'Eric Idle'
>>> f'''Eric Idle'''
'Eric Idle'

Если вам нужно использовать одинаковый тип кавычки как внутри, так и снаружи строки, вы можете сделать это с помощью \:

>>> f"The \"comedian\" is {name}, aged {age}."
'The "comedian" is Eric Idle, aged 74.'

Словари

Говоря о кавычках, следите, когда вы работаете со словарями. Если вы собираетесь использовать одинарные кавычки для ключей словаря, то не забудьте убедиться, что вы используете двойные кавычки для f-строк, содержащих ключи.

>>> comedian = {'name': 'Eric Idle', 'age': 74}
>>> f"The comedian is {comedian['name']}, aged {comedian['age']}."
The comedian is Eric Idle, aged 74.

Пример с синтаксической ошибкой:

>>> comedian = {'name': 'Eric Idle', 'age': 74}
>>> f'The comedian is {comedian['name']}, aged {comedian['age']}.'
  File "<stdin>", line 1
    f'The comedian is {comedian['name']}, aged {comedian['age']}.'
                                    ^
SyntaxError: invalid syntax

Если вы используете тот же тип кавычки вокруг ключей словаря, что и на внешней стороне f-строки, то кавычка в начале первого ключа словаря будет интерпретироваться как конец строки.

Фигурные скобки

Чтобы в скобках появилась скобка, вы должны использовать двойные скобки:

>>> f"{{74}}"
'{74}'

Обратите внимание, что использование тройных скобок приведет к тому, что в вашей строке будут только одиночные скобки:

>>> f"{{{74}}}"
'{74}'

Тем не менее, вы можете получить больше фигурных скобок, если вы используете больше, чем тройные фигурные скобки:

>>> f"{{{{74}}}}"
'{{74}}'

Обратный слеш

Как вы видели ранее, вы можете использовать обратные слэши в строковой части f-строки. Однако вы не можете использовать обратную косую черту для экранирования части выражения f-строки:

>>> f"{\"Eric Idle\"}"
  File "<stdin>", line 1
    f"{\"Eric Idle\"}"
                      ^
SyntaxError: f-string expression part cannot include a backslash

Вы можете обойти это, предварительно посчитав выражение и используя результат в f-строке:

>>> name = "Eric Idle"
>>> f"{name}"
'Eric Idle'

Встроенные комментарии

Выражения не должны содержать комментарии, использующие символ #. Используя это вы получите синтаксическую ошибку:

>>> f"Eric is {2 * 37 #Oh my!}."
  File "<stdin>", line 1
    f"Eric is {2 * 37 #Oh my!}."
                                ^
SyntaxError: f-string expression part cannot include '#'

Заключение

Вы по-прежнему можете использовать более старые способы форматирования строк, но с f-строками у вас теперь есть более лаконичный, читаемый и удобный способ, который быстрее и менее подвержен ошибкам. Упрощение вашей жизни с помощью f-строк – отличная причина начать использовать Python 3.6, если вы еще не сделали этого. (Если вы все еще используете Python 2, не забудьте, что 2020 скоро наступит!)

Согласно Zen of Python, когда вам нужно решить, как что-то сделать, должен быть один – и предпочтительно только один – очевидный способ сделать это. Хотя f-строки не единственный возможный способ отформатировать строки, они в состоянии стать тем очевидным и единственным способом сделать эту работу.

Дальнейшее чтение

Если вы хотите прочитать расширенное обсуждение интерполяции строк, взгляните на PEP 502. Кроме того, в черновике PEP 536 есть еще несколько мыслей о будущем f-строк.

Оригинальная статья by Joanna Jablonski  Python 3’s f-Strings: An Improved String Formatting Syntax (Guide)

Была ли вам полезна эта статья?
[14 / 4.4]

Spread the love
Подписаться
Уведомление о
guest
1 Комментарий
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Андрей
Андрей
3 лет назад

Большое спасибо за предложенную статью.Желательно бы более примеров форматирования с использованием Мини-язык спецификации формата