Ответ 1
Тайм-аут IPython по какой-то причине отключен (хотя при тестировании с более длинной строкой формата в разных ячейках он вел себя немного лучше). Возможно, выполнение в одних и тех же ячейках неверно, не знаю.
В любом случае "{}"
бит быстрее, чем "{pos}"
, который быстрее, чем "{name}"
, в то время как все они медленнее, чем str
.
str(val)
- самый быстрый способ преобразования объекта в str
; он прямо вызывает объекты __str__
, если он существует, и возвращает результирующую строку. Другие, такие как format
, (или str.format
), включают дополнительные накладные расходы из-за дополнительного вызова функции (до самого format
); обрабатывая любые аргументы, анализируя строку формата и затем вызывая __str__
их args
.
Для методов str.format
"{}"
используется автоматическая нумерация; из небольшого раздела в docs в синтаксисе формата:
Изменено в версии 3.1: Спецификаторы позиционного аргумента могут быть опущены, поэтому
'{} {}'
эквивалентно'{0} {1}'
.
то есть, если вы укажете строку формы:
"{}{}{}".format(1, 2, 3)
CPython сразу же знает, что это эквивалентно:
"{0}{1}{2}".format(1, 2, 3)
С строкой формата, содержащей цифры с указанием позиций; CPython не может принимать строго возрастающее число (которое начинается с 0
) и должно анализировать каждую отдельную скобку, чтобы получить ее право, немного замедляя процесс:
"{1}{2}{0}".format(1, 2, 3)
То, почему это также не позволяет смешать эти два вместе:
"{1}{}{2}".format(1, 2, 3)
когда вы попытаетесь сделать это, вы получите хороший ValueError
:
ValueError: cannot switch from automatic field numbering to manual field specification
он также захватывает эти позиционные элементы с PySequence_GetItem
, которые, я уверен, являются быстрыми, по крайней мере, по сравнению с PyObject_GetItem
[см. следующий].
Для значений "{name}"
у CPython всегда есть дополнительная работа, потому что мы имеем дело с ключевыми словами, а не с позиционными; это включает в себя такие вещи, как построение словаря для вызовов и генерация более LOAD
инструкций байтового кода для загрузки key
и значений. Ключевая форма вызова функции всегда вводит некоторые накладные расходы. Кроме того, кажется, что захват фактически использует PyObject_GetItem
, который несет некоторые дополнительные накладные расходы из-за его родового характера.