С версии Python 3.14 появилась поддержка символа подчеркивания и запятой в качестве разделителей тысяч для типов представления чисел с плавающей запятой при использовании нового стиля строкового форматирования (с помощью
str.format()илиf-строк). Примеры смотрите ниже.
"F-строки" обеспечивают краткий, читаемый способ включения значения выражений Python внутри строк. В исходном коде Python форматированная строка или по другому f-string - это буквальная строка с префиксом 'f' или 'F', которая содержит выражения внутри фигурных скобок {}. Выражения заменяются их значениями.
Escape-последовательности декодируются как в обычных строковых литералах, за исключением случаев, когда литерал также помечается как необработанная строка r'string'.
Части строки вне фигурных скобок обрабатываются буквально, за исключением того, что любые двойные фигурные скобки {{ или }} заменяются соответствующей одиночной фигурной скобкой. Одна открывающая фигурная скобка { обозначает поле замены, которое начинается с выражения Python. После выражения может быть поле преобразования, введенное восклицательным знаком !. Спецификатор формата также может быть добавлен, введенный двоеточием :. Поле замены заканчивается закрывающей фигурной скобкой }.
Выражения в форматированных строках рассматриваются как обычные выражения Python, окруженные круглыми скобками.
Пустое выражение недопустимо.
Как лямбда-выражения, так и выражения присваивания := должны быть заключены в явные круглые скобки.
Каждое выражение вычисляется в контексте, где отображается форматированный строковый литерал, в порядке слева направо.
В Python 3.14 Появилась поддержка символа подчеркивания и запятой в качестве разделителей тысяч для типов представления чисел с плавающей точкой при использовании нового стиля строкового форматирования (с помощью str.format() или f-строк).
x = 1234567.8912345 # С запятыми print(f"Вывод: {x:,.2f}") # Вывод: 1,234,567.89 # С подчеркиваниями print(f"Вывод: {x:_.2f}") # Вывод: 1_234_567.89
До версии Python 3.12 кавычки в выражениях f-string не должны были конфликтовать с кавычками, используемыми во внешнем форматированном строковом литерале. В Python 3.12 это ограничение снято.
До версии Python 3.12 выражения (в фигурных скобках) могли содержать переносы только в строках с тройными кавычками, но не могли содержать комментарии. В Python 3.12 ограничение на использование переносов строк и комментариев было снято.
В Python 3.12, все, что идет после # внутри поля замены, является комментарием (!!! даже закрывающие скобки и кавычки). В этом случае поля замены необходимо закрыть в другой строке.
>>> a = 2 >>> f'abc{a # This is a comment }' ... + 3}' # 'abc5'
А еще в Python 3.12 стало возможным делать такие вещи:
>>> f"This is the playlist: {", ".join([ ... 'Take me back to Eden', # My, my, those eyes like fire ... 'Alkaline', # Not acid nor alkaline ... 'Ascensionism' # Take to the broken skies at last ... ])}" 'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
С версии Python 3.12 в полях замены стала доступна для использования обратная косая черта и оценивается так же, как и в любом другом контексте. Это означает, что выражения могут содержать символы новой строки '\n' как в одинарных, так и в тройных кавычках.
a = ["a", "b", "c"] print(f"List a contains:\n{"\n".join(a)}") # List a contains: # a # b # c
В Python 3.8 добавлен спецификатор '='. Если указан знак равенства =, то выходные данные будут содержать текст выражения, знак = и вычисленное значение. Пробелы после открывающей скобки '{', внутри выражения и после '=' сохраняются в выходных данных. По умолчанию '=' приводит к предоставлению repr() выражения, если не указан формат. Когда указан формат, по умолчанию используется str() выражения, если не объявлено преобразование '!r'.
>>> a = 1 >>> f'{a + 1 = }' # 'a + 1 = 2'
Если указано преобразование (!o или !a или !r), то перед форматированием результат вычисления выражения преобразуется. Преобразование '!s' вызывает str() для результата, '!r' вызывает repr(), а '!a' вызывает ascii(). Затем результат форматируется с помощью протокола str.format(). Спецификатор формата передается в метод __format__() выражения или результата преобразования. Отформатированный результат затем включается в конечное значение всей строки.
Спецификация формата Mini-Language совпадает с языком, используемым во встроенной функции format().
f-строки нельзя использовать в качестве строк документации, даже если они не содержат выражений.
В качестве положительного побочного эффекта от того, как была реализована новая функциональность в Python 3.12 (путем анализа f-строк с помощью синтаксического анализатора PEG), сообщения об ошибках стали включать её точное местоположение. Например, до версии Python 3.12 следующая f-строка вызывает SyntaxError:
>>> my_string = f"{x z y}" + f"{1 + 1}" # File "<stdin>", line 1 # (x z y) # ^^^ # SyntaxError: f-string: invalid syntax. Perhaps you forgot a comma?
Сообщение об ошибке не содержит точного местоположения внутри строки, а также содержит выражение, искусственно заключенное в круглые скобки. В Python 3.12 сообщения об ошибках стали более точными и могут отображать всю строку:
>>> my_string = f"{x z y}" + f"{1 + 1}" # File "<stdin>", line 1 # my_string = f"{x z y}" + f"{1 + 1}" # ^^^ # SyntaxError: invalid syntax. Perhaps you forgot a comma?
'=' в f-строках;if/else в f-строке;datetime.datetime и datetime.date;>>> name = 'Fred' >>> f'He said his name is {name!r}.' # 'He said his name is 'Fred'.' # repr() является эквивалентом '!r' >>> f'He said his name is {repr(name)}.' # He said his name is 'Fred'.
>>> import decimal >>> width = 10 >>> precision = 4 >>> value = decimal.Decimal("12.34567") >>> f'result: {value:{width}.{precision}}' 'result: 12.35'
До версии Python 3.12 кавычки в полях замены/выражениях f-string не должны конфликтовать с кавычками, используемыми во внешнем форматированном строковом литерале:
>>> a = {'x': 120} >>> f'abc {a['x']} def' # File "<stdin>", line 1 # f'abc {a['x']} def' # ^ # SyntaxError: invalid syntax # Нужно было использовать различные кавычки f"abc {a['x']} def" # 'abc 120 def'
В версии Python 3.12 и выше теперь можно делать такие вещи (обратите внимание, что кавычки " не конфликтуют):
>>> songs = ['Take me back to Eden', 'Alkaline', 'Ascensionism'] >>> f"This is the playlist: {", ".join(songs)}" # 'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
Обратите внимание, что до Python 3.12 не было явного ограничения на вложение f-строк, но тот факт, что строковые кавычки не могли быть повторно использованы внутри компонента выражения f-string, делал невозможным произвольное вложение f-строк. Фактически, это самая вложенная f-строка, которую можно написать:
>>> f"""{f'''{f'{f"{1+1}"}'}'''}""" '2'
Так как в Python 3.12 и выше f-строки могут содержать любое допустимое выражение Python внутри компонентов выражения, то теперь f-строки можно вкладывать произвольное количество раз:
>>> f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" # '2'
До версии Python 3.12 выражения f-string не могли содержать ни одного символа \. Это также повлияло на управляющие последовательности unicode (такие как \N{snowman}), поскольку они содержат часть \N, которая ранее не могла быть частью компонентов выражения f-строк.
Пример того, что до версии Python 3.12 обратные косые черты не допускались внутри компонента выражения f-строк и вызывали ошибку:
>>> f'newline: {ord("\n")}' # File "<stdin>", line 1 # SyntaxError: f-string expression part cannot include a backslash
Чтобы включить значение, в котором используется обратная косая черта, нужно было создать временную переменную.
>>> newline = ord('\n') >>> f'newline: {newline}' # 'newline: 10'
В версии Python 3.12 и выше стало возможным определить выражения следующим образом:
>>> songs = ['Take me back to Eden', 'Alkaline', 'Ascensionism'] >>> print(f"This is the playlist: {"\n".join(songs)}") # This is the playlist: Take me back to Eden # Alkaline # Ascensionism >>> print(f"This is the playlist: {"\N{BLACK HEART SUIT}".join(songs)}") # This is the playlist: Take me back to Eden♥Alkaline♥Ascensionism
F-строки используют одинарные фигурные скобки {} для вывода выражений Python. Но как быть, если в итоговой строки необходим вывод самой фигурной скобки? Чтобы в итоговой строке появились фигурные скобки, необходимо использовать двойные скобки, при этом выражение Python вычисляться не будет:
>>> num = 53 >>> f"{{num}}" # {num}
Обратите внимание, что если нужно вычислить выражение Python и при этом вывести скобки, то нужно использовать тройные скобки:
>>> num = 53 >>> f"{{{num}}}" # {53}
Другими словами для итогового вывода одной скобки в f-строке, необходимо использовать две скобки + одна, если нужно вычислить выражение. Для вывода 2-х скобок, в f-строке используйте 4 + 1 для вычисления выражения Python, и так далее (в общем четное количество + одна, если нужно вычислить выражение ):
>>> num = 53 >>> f"{{{{{num}}}}}" # {{53}}
До Python 3.12 сами выражения f-string (в фигурных скобках) должны были быть определены только в одной строке при использовании одинарных кавычек или могли содержать переносы строк только в строках с тройными кавычками, что было не совсем удобно.
>>> f"""This is the playlist: {", ".join([ ... 'Take me back to Eden', ... 'Alkaline', ... 'Ascensionism' ... ])}""" # 'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
В Python 3.12 это ограничение снято и теперь можно определять f-строки, выражения которых охватывают несколько строк, при этом разрешено повторное использование одинаковых кавычек во внешнем обрамлении f-строки и внутри выражения:
>>> f"This is the playlist: {", ".join([ ... 'Take me back to Eden', ... 'Alkaline', ... 'Ascensionism' ... ])}" # 'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
'=' в f-строках:Для документирования выражений и отладки в Python 3.8 к f-строкам добавлен спецификатор '='. F-строка, такая как f'{expr=}', расширится до текста выражения и знака равенства, а затем представления вычисляемого выражения. Например:
>>> import datetime >>> user = 'eric_idle' >>> member_since = datetime.date(1975, 7, 31) >>> f'{user=} {member_since=}' # "user='eric_idle' member_since=datetime.date(1975, 7, 31)"
Обычные спецификаторы формата f-string позволяют более точно контролировать способ отображения результата выражения:
>>> import datetime >>> delta = datetime.date.today() - member_since >>> f'{user=!s} {delta.days=:,d}' # 'user=eric_idle delta.days=16,075'
Спецификатор = будет отображать все выражение, чтобы можно было показать вычисления:
>>> from math import cos, radians >>> theta = 30 >>> print(f'{theta=} {cos(radians(theta))=:.3f}') theta=30 cos(radians(theta))=0.866
if/else в f-строке.>>> a = 10 >>> b = 5 >>> f"{a if a > b else b}" # `10` >>> f"{a if a < b else b}" # `5`
Форматирование datetime.date
>>> from datetime import date, datetime >>> day = date(year=2022, month=9, day=1) >>> f"{day}" # 2022-09-01 # формат по умолчанию >>> f"{day:%Y-%m-%d}" # 2022-09-01 # использование / в качестве разделителя >>> f"{day:%Y/%m/%d}" # 2022/09/01 # Преобразование месяца в текст (короткая/длинная версия) >>> f"{day:%Y %b %d}" # 2022 Sep 01 >>> f"{day:%Y %B %d}" # 2022 September 01 # Повторное использование одной и той же переменной несколько раз и в разных форматах >>> f"{day:%b or %B}?" # Sep or September? >>> f"{day:%Y %Y %Y}" # 2022 2022 2022 >>> f"{day:%Y %b %d (%A)}" # 2022 Sep 01 (Thursday) >>> f"{day:%y.%m.%d}" # 22.09.01
Форматирование datetime.datetime
day_and_time = datetime( year=2022, month=9, day=1, hour=17, minute=30, second=45 ) >>> now = datetime.now() >>> f"{day_and_time}" # 2022-09-01 17:30:45 >>> f"{now}" # с микросекундами # 2023-01-17 10:15:11.858254 # формат по умолчанию: >>> f"{now:%Y-%m-%d %H:%M:%S.%f}" # 2023-01-17 10:15:11.858254 >>> type(f"{now:%Y-%m-%d %H:%M:%S.%f}") # str # формат по умолчанию с уменьшенной точностью микросекунд >>> f"{now:%Y-%m-%d %H:%M:%S.%f}"[:22] # 2023-01-17 10:15:11.85 # Изменяем 24-часовой формат на 12-часовой: >>> f"24hr: {day_and_time:%Y-%m-%d %H:%M:%S}" # 24hr: 2022-09-01 17:30:45 >>> f"12hr: {day_and_time:%Y-%m-%d %I:%M:%S}" # 12hr: 2022-09-01 05:30:45 >>> f"12hr with AM/PM: {day_and_time:%Y-%m-%d %I:%M:%S %p}" # 12hr with AM/PM: 2022-09-01 05:30:45 PM
Примечание: другие полезные приемы форматирования дат.
day = date( year=2018, month=9, day=17 ) >>> f"The date: {day}" # The date: 2018-09-17 >>> f"Day of the year: {day: %j}" # Day of the year: 260 >>> f"Week of the year (Mon): {day: %W}" # Week of the year (Mon): 38 >>> f"Week of the year (Sun): {day: %U}" # Week of the year (Sun): 37
Форматированные строковые литералы нельзя использовать в качестве строк документации, даже если они не содержат выражений.
>>> def foo(): ... f'Not a docstring' ... >>> foo.__doc__ is None True
str.format().>>> tmp = "R: {r}\nG: {g}\nB: {b}" >>> rgb = {'r': 123, 'g': 145, 'b': 255} >>> print(tmp.format(**rgb)) # R: 123 # G: 145 # B: 255 >>> tmp = "Шаблон строки: {}" >>> line = "Привет" >>> tmp.format(line) # 'Шаблон строки: Привет'
>>> b = 2999 >>> pi = 3.1415926 >>> f'Pi={pi:.3f}, b={b:*^11.2f}' # 'Pi=3.142, b=**2999.00**' >>> print("\n".join(f'{a:{a}<{a}}' for a in range(1, 6))) # 1 # 22 # 333 # 4444 # 55555 # форматирование процентов >>> perc = 34 / 87 >>> perc # 0.39080459770114945 >>> f"Процентное отношение: {perc:%}" # 'Процентное отношение: 39.080460%' >>> f"Процентное отношение: {perc:.2%}" # 'Процентное отношение: 39.08%'
float в f-строках.>>> pi_val = 3.141592 >>> f"Example 1: {pi_val:f}" # Example 1: 3.141592 >>> f"Example 2: {pi_val:.0f}" # Example 2: 3 >>> f"Example 3: {pi_val:.1f}" # Example 3: 3.1 >>> f"Example 4: {pi_val:.3f}" # Example 4: 3.142
Примечание: возможны вложенные выражения.
>>> float_val = 1.5 >>> precision = 3 >>> f"{float_val:.{precision}f}" # 1.500
>>> val = 0.5 >>> f"Example 1: {val:%}" # Example 1: 50.000000% >>> f"Example 2: {val:.0%}" # Example 2: 50% >>> val = 1.255 >>> f"Example 1: {val:.0%}" # Example 1: 125% >>> f"Example 2: {val:.1%}" # Example 2: 125.5%
>>> val = 1.23e3 # 1.23 * 10^3 >>> f"Example 1: {val:e}" # Example 1: 1.230000e+03 >>> f"Example 2: {val:E}" # Example 2: 1.230000E+03 # ограниченная точность >>> val = 1.2345e3 >>> f"{val:.2e}" # 1.23e+03 # Вывод обычного числа в научной записи >>> val = 2022 >>> f"{val:.3e}" # 2.022e+03
val = 1 f"{val:d}" 1 # Печать разделителей тысяч int_1 = 1000 int_2 = 1000_000_000 f"{int_1:,d}" 1,000 f"{int_2:,d}" 1,000,000,000
>>> val_int = 1 >>> val_float = 1.234 >>> val_scient = 4.567e2 >>> f"{val_int =: n}" # val_int = 1 >>> f"{val_float =: n}" # val_float = 1.234 >>> f"{val_scient =: n}" # val_scient = 456.7 >>> val_float_1 = 1.234 >>> val_float_2 = 20.234 >>> val_float_3 = 123.456 >>> f"{val_float_1 =: .2n}" # печатается в виде усеченного плавающего значения # val_float_1 = 1.2 >>> f"{val_float_2 =: .2n}" # печатается как int # val_float_2 = 20 >>> f"{val_float_3 =: .2n}" # печатается в виде научной записи # val_float_3 = 1.2e+02
>>> greetings = "hello" # отступы справа и слева >>> f"{greetings:>10}" # ' hello' >>> f"{greetings:<10}" # 'hello ' # выравнивание чисел >>> a = "1" >>> b = "21" >>> c = "321" >>> d = "4321" >>> print("\n".join((f"{a:>10}", f"{b:>10}", f"{c:>10}", f"{d:>10}"))) # 1 # 21 # 321 # 4321 # выравнивание посередине >>> hello = "world" >>> f"{hello:^11}" # ' world ' >>> f"{hello:*^11}" # '***world***'
>>> number = 1024 >>> f"{number:#0x}" '0x400'
В Python 3.14 Появилась поддержка символа подчеркивания и запятой в качестве разделителей тысяч для типов представления чисел с плавающей точкой
x = 1234567.8912345 # С запятыми print(f"Вывод: {x:,.2f}") # Вывод: 1,234,567.89 # С подчеркиваниями print(f"Вывод: {x:_.2f}") # Вывод: 1_234_567.89 # С отрицательными числами y = -9876543.210987 print(f"Вывод: {y:,.3f}") # Вывод: -9,876,543.211 # С нулями после точки z = 1234.0 print(f"Вывод: {z:,.2f}") # Вывод: 1,234.00