Простой ответ заключается в том, что f-строки являются частью грамматики и синтаксиса языка. С другой стороны, вызов str()
требует поиска в таблице символов, за которой следуетвызов функции.
Вот аналогичный пример, который интерполирует целочисленную переменную, сопоставьте это с интерполяцией константного значения.
x = 1
%timeit f'{1}'
%timeit f'{x}'
%timeit str(1)
%timeit str(x)
113 ns ± 2.25 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
166 ns ± 4.71 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
342 ns ± 23.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
375 ns ± 11.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Разница в поведении очевидна, когда вы смотрите надизассемблированный байт-код с dis
.
import dis
dis.dis("f'{x}'")
1 0 LOAD_NAME 0 (x)
2 FORMAT_VALUE 0
4 RETURN_VALUE
dis.dis("str(x)")
1 0 LOAD_NAME 0 (str)
2 LOAD_NAME 1 (x)
4 CALL_FUNCTION 1
6 RETURN_VALUE
Тяжелый подъем - это все в инструкции CALL_FUNCTION
, накладные расходы, которые, безусловно, не несут f-струныне имеет - по крайней мере, в этом случае, поскольку ничего не должно быть eval
'd.