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

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

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

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

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

*Бесплатная загрузка PDF:* https://realpython.com/bonus/python-cheat-sheet-short/[Python 3 Шпаргалка]

«Старая школа» Форматирование строк в Python

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

Вариант № 1:% форматирования

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

_ _ «Операции форматирования, описанные здесь, демонстрируют различные причуды, которые приводят к ряду распространенных ошибок (таких как неправильный вывод кортежей и словарей)

Использование более новых форматированных строковых литералов или интерфейса + str.format () + помогает избежать этих ошибок. Эти альтернативы также предоставляют более мощные, гибкие и расширяемые подходы к форматированию текста ». (Https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting[Source]) _ _

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

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

>>>

>>> 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 docs для получения дополнительной информации.

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

+ str.format () + является улучшением% -форматирования. Он использует обычный синтаксис вызова функции и может быть extensible через формат `+ () + `method для объекта, преобразуемого в строку.

С помощью + 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-Strings: новый и улучшенный способ форматирования строк в Python

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

Также называемые «отформатированные строковые литералы», f-строки - это строковые литералы, которые имеют в начале + f + и фигурные скобки, содержащие выражения, которые будут заменены их значениями. Выражения оцениваются во время выполнения, а затем форматируются с использованием протокола + format +. Как всегда, Python docs - ваш друг, когда вы хотите узнать больше.

Вот несколько способов, которыми 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.'

Ты еще любишь струны? Я надеюсь, что к концу этой статьи вы ответите на https://twitter.com/dbader_org/status/992847368440561664 [+ >>> F" Да! "+].

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

Поскольку 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.'

The + 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, вы можете сделать это https://mail.python.org/pipermail/python-ideas/2015-July/034726.html [ Вот].

Многострочные струны

Вы можете иметь многострочные строки:

>>>

>>> 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}.'

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

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

>>>

>>> 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'

Ознакомьтесь с рекомендациями по отступам в PEP 8.

скорость

+ F + в f-строках может также означать "быстрый".

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

_ «F-строки обеспечивают способ встраивания выражений в строковые литералы, используя минимальный синтаксис. Следует отметить, что f-строка на самом деле является выражением, вычисляемым во время выполнения, а не постоянным значением. В исходном коде Python f-строка является литеральной строкой с префиксом + f +, которая содержит выражения внутри фигурных скобок. Выражения заменяются их значениями ». (Https://www.python.org/dev/peps/pep-0498/#abstract[Source]) _

Во время выполнения выражение внутри фигурных скобок оценивается в собственной области видимости и затем помещается вместе со строковым литералом в часть 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-струны выходят на первое место.

Однако это не всегда так. Когда они были впервые реализованы, у них было несколько https://stackoverflow.com/questions/37365311/why-are-literal-formatted-strings-so-slow-in-python-3-6-alpha-now-fixed-in -3-6 [проблемы со скоростью] и должны быть сделаны быстрее, чем + str.format () +. Был представлен специальный https://bugs.python.org/issue27078 [+ BUILD_STRING + код операции].

Python f-Strings: досадные детали

Теперь, когда вы узнали все о том, почему 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, когда вам нужно решить, как что-то сделать, тогда «[t] здесь должно быть одно - и желательно только один - очевидный способ сделать это. Несмотря на то, что f-строки не являются единственным возможным способом форматирования строк, они находятся в прекрасном положении, чтобы стать тем очевидным способом выполнения работы.

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

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

*Бесплатная загрузка PDF:* https://realpython.com/bonus/python-cheat-sheet-short/[Python 3 Шпаргалка]

Для большего удовольствия со строками, проверьте следующие статьи:

Счастливого Pythoning!