F-строки в Python 3.6
Мне действительно нравится углубляться в стиль кода, и мне интересно знать, будет ли с этого момента во всех случаях лучше использовать новый стиль.
Я .format()
использую .format()
в моих проектах Python 3.5, и я боюсь, что он будет устаревшим в следующих версиях Python из-за этого нового типа строковых литералов.
>>> name = "Test"
>>> f"My app name is {name}."
'My app name is Test.'
Приходит ли возможность форматированной строки полностью заменить старый format()
?
Я понимаю, что это основано на идее, что:
Простое лучше, чем сложное.
Однако, как насчет проблем с производительностью, есть ли разница между ними? Или это просто простой вид той же функции?
Ответы
Ответ 1
Я боюсь, что это будет устаревшим во время следующих версий Python
Не str.format
, что str.format
, по-видимому, не имеет (и не имеет причин) уходить в ближайшее время, PEP, который ввел f
префиксных строк, даже в своем резюме:
Этот PEP не предлагает удалять или исключать какой-либо из существующих механизмов форматирования строк.
Форматированные строки были введены для устранения некоторых недостатков других методов форматирования строк; не выбрасывать старые методы и не заставлять бог знает, сколько проектов используют f-строку, если они хотят, чтобы их код работал для Python 3. 6+.
Что касается производительности, кажется, что я изначально подозреваю, что они могут быть медленнее, это неправильно, f-строки, кажется, легко превосходят своих аналогов .format
:
➜ cpython git:(master) ./python -m timeit -s "a = 'test'" "f'formatting a string {a}'"
500000 loops, best of 5: 628 nsec per loop
➜ cpython git:(master) ./python -m timeit "'formatting a string {a}'.format(a='test')"
100000 loops, best of 5: 2.03 usec per loop
На момент написания статьи это было сделано в отношении основной ветки репозитория CPython; они определенно могут быть изменены:
-
f-strings
, как новая функция, могут иметь возможные оптимизации - Оптимизация под CPython может сделать
.format
быстрее (например, вызовы метода Speedup 1.2x)
Но на самом деле, не стоит так сильно беспокоиться о скорости, беспокоиться о том, что более читабельно для вас и для других.
Во многих случаях это будут f-strings
, но в некоторых случаях format
лучше.
Ответ 2
Чтобы использовать Jim для ответа на ваш вопрос о производительности, я использовал модуль python dis
для сравнения инструкций байткода для двух синтаксически отличных, но функционально эквивалентных функций.
import dis
def f1():
a = "test"
return f"{a}"
def f2():
return "{a}".format(a='test')
print(dis.dis(f1))
print(dis.dis(f2))
Результат:
11 0 LOAD_CONST 1 ('test')
2 STORE_FAST 0 (a)
12 4 LOAD_FAST 0 (a)
6 FORMAT_VALUE 0
8 RETURN_VALUE
None
15 0 LOAD_CONST 1 ('{a}')
2 LOAD_ATTR 0 (format)
4 LOAD_CONST 2 ('test')
6 LOAD_CONST 3 (('a',))
8 CALL_FUNCTION_KW 1
10 RETURN_VALUE
None
Можно видеть, что f-строка обрабатывает форматирование без вызовов атрибутов или функций, что может налагать проверку типов и накладные расходы памяти. Согласно timeit
, это дает примерно 3-кратное увеличение производительности (для моих конкретных функций)
>>> timeit.timeit('f1()', 'from __main__ import f1', number=100000)
0.012325852433775708
>>> timeit.timeit('f2()', 'from __main__ import f2', number=100000)
0.036395029920726074
Ответ 3
Одна вещь, не упомянутая (которая делает невозможным устаревание старых методов), состоит в том, что интерполяция предназначена только для строковых литералов. Это означает, что строка отображается один раз во время выполнения. Шаблон нельзя использовать снова с обновленными переменными, например:
str_template.format(args)
Другой случай - i18n, где используется string.Template. Многие варианты использования были бы невозможны без более старых методов. Наслаждайтесь интерполяцией строк, но не используйте ее там, где она не подходит, то есть там, где вам нужен шаблон многократного использования.
Ответ 4
Если вы хотите поддерживать Python 3.5, вы можете использовать fstring
pip install fstring
from fstring import fstring
x = 1
y = 2.0
plus_result = "3.0"
print fstring("{x}+{y}={plus_result}")
# Prints: 1+2.0=3.0