Эта статья из серии «Почему Python», пожалуйста, проверьтеВсе статьи
При ежедневном использовании Python нам часто нужно создавать список Я думаю, что все очень опытны, верно?
# 方法一:使用成对的方括号语法
list_a = []
# 方法二:使用内置的 list()
list_b = list()
Какой из двух способов написания выше вы часто используете? Вы думали о разнице между ними?
Перейдем сразу к делу и бросим вопросы этой статьи напрямую:Из двух способов написания списка, [] и list(), какой быстрее и почему?
Примечание. Чтобы упростить задачу, в качестве примера для анализа возьмем создание пустого списка. Дополнительные сведения и инструкции по использованию списка см.эта статья
1. [] в три раза быстрее, чем list()
Для первого вопроса используйтеtimeit
Функцию модуля timeit() можно легко вычислить:
>>> import timeit
>>> timeit.timeit('[]', number=10**7)
>>> timeit.timeit('list()', number=10**7)
Как показано на рисунке выше, когда каждый вызывается 10 миллионов раз, метод создания [] занимает всего 0,47 секунды, а метод создания list() занимает 1,75 секунды, поэтому последний занимает в 3,7 раза больше времени!
Это отвечает на предыдущий вопрос:[] намного быстрее, чем list() при создании пустого списка.
Примечание. Эффективность функции timeit() зависит от среды выполнения, и результат каждого выполнения будет немного отличаться. Я несколько раз экспериментировал с Python 3.8, и в целом [] работает чуть более чем в 3 раза быстрее, чем list() .
2. list() имеет больше шагов выполнения, чем []
Итак, перейдем ко второму вопросу: почему [] быстрее?
На этот раз мы можем использоватьdis
Функция dis() модуля, чтобы увидеть, в чем разница в байт-коде, выполняемом двумя:
>>> from dis import dis
>>> dis("[]")
>>> dis("list()")
Как показано выше, байт-код [] имеет две инструкции (BUILD_LIST и RETURN_VALUE), а байт-код list() имеет три инструкции (LOAD_NAME, CALL_FUNCTION и RETURN_VALUE).
Что означают эти инструкции? Как их понять?
Во-первых, для [] это набор литералов в Python, которые, как литералы, такие как числа, представляют точное фиксированное значение.
То есть, когда Python анализирует его, он знает, что хочет представить список, поэтому он напрямую вызывает метод построения списка в интерпретаторе (соответствующий BUILD_LIST ) для создания списка, так что это один шаг.
Для list() «список» — это просто общее имя, а не литерал, что означает, что интерпретатор сначала не распознает его.
Поэтому первый шаг интерпретатора — найти это имя (соответствующее LOAD_NAME). Он будет искать в каждой области по одной в определенном порядке (локальная область -- глобальная область -- встроенная область), пока не будет найден, если не будет найден, он выкинетNameError
.
Интерпретатор видит пару круглых скобок после «списка», поэтому вторым шагом является вызов имени как вызываемого объекта, то есть вызов его как функции (соответствующей CALL_FUNCTION).
Поэтому, когда list() создает список, ему необходимо пройти два этапа поиска имени и вызова функции, прежде чем он сможет фактически начать создавать список (Примечание: CALL_FUNCTION будет иметь несколько процессов вызова функций внизу для достижения той же логики как BUILD_LIST, это мы игнорируем).
На этом этапе мы можем ответить на предыдущий вопрос:Поскольку list() включает в себя больше шагов выполнения, он медленнее, чем [].
3. Улучшена скорость list()
Прочитав процесс ответов на первые два вопроса, вы можете почувствовать, что это недостаточно весело, и вы можете почувствовать, что даже если вы знаете это холодное знание, оно не сильно поможет.Кажется, небольшое улучшение незначительно .
но мыPython猫
ПроизведеноПочему PythonСерия всегда придерживалась неутомимого духа поиска знаний, невозможно оставить этот вопрос без ответа.
Более того, по привычке к дивергентному мышлению я задумался еще над одним очень интересным вопросом:Можно ли улучшить скорость list()?
я писал некоторое время назадстатьяПросто чтобы обсудить эту проблему, то есть в только что выпущенной версии Python 3.9.0 реализован более быстрый протокол векторного вызова для list(), поэтому скорость выполнения будет в определенной степени улучшена.
Заинтересованные студенты могут перейти кофициальный сайт питонаСкачать версию 3.9.
Согласно моим многочисленным результатам тестов, запуск list() 10 миллионов раз в новой версии занимает около 1 секунды, что в 2 раза больше, чем время выполнения []. текущая версия в целом значительно улучшена.
До сих пор мы ответили на ряд вопросов, если вы чувствуете, что что-то приобрели, пожалуйста, поставьте лайк и поддержите! Добро пожаловать, чтобы обратить внимание на более захватывающий контент в будущем.
Эта статья относится к серии «Почему Python» (подготовленной Python Cat), которая в основном посвящена таким темам, как синтаксис, дизайн и разработка Python, и пытается показать очаровательное очарование Python, начиная с вопросов «почему». Все статьи будут заархивированы на Github, всем желающим поставить маленькую звездочку, адрес проекта:GitHub.com/Китайский макияж…