Вы не можете думать о Python, как о C или C ++. Затраты на постоянные множители дополнительной копии намного ниже, чем издержки на постоянные множители, связанные с поддержкой всех динамических функций Python, особенно без JIT в CPython. Вы не можете предполагать, что сохранение одной копии действительно поможет, если учесть другие вещи, которые нужно изменить, чтобы избежать этой копии.
В этом случае почти вся работа заключается в преобразовании списка. Копия, которую вы сохраняете, не имеет смысла. Сравните время для b[i:]
и list(b[i:])
, и вы увидите, что срезы составляют всего несколько процентов времени выполнения, даже когда срез выполняет копирование.
Копия, которую вы сохраняете, не имеет значения, потому что это просто memcpy
. Напротив, для преобразования списка необходимо создать итератор по строке байтов или просмотру памяти, повторно вызывать слот tp_iternext
итератора, получать int
объекты, соответствующие необработанным байтам памяти и т. Д., Что намного дороже. Это даже дороже для вида памяти, потому что объекты вида памяти должны поддерживать многомерные формы и небайтовые типы данных, а также потому, что реализация вида памяти не имеет выделенной реализации __iter__
, поэтому она проходит через стандартную итеративную резервную итерацию , который медленнее.
Вы можете сэкономить некоторое время, используя метод tolist
вида памяти вместо вызова list
. Это пропускает кучу накладных расходов итерационного протокола и позволяет выполнять некоторые проверки только один раз, а не один раз для каждого элемента. В моих тестах это почти так же быстро, как вызов list
для строки байтов.