Я обнаружил, что в Python 3.14 список создаётся быстрее кортежа. На моём компьютере разница появляется примерно с ~20 элементов.
Довольно любопытно. За счёт чего это получилось? Нельзя ли применить такую же оптимизацию к кортежам?
Я обнаружил, что в Python 3.14 список создаётся быстрее кортежа. На моём компьютере разница появляется примерно с ~20 элементов.
Довольно любопытно. За счёт чего это получилось? Нельзя ли применить такую же оптимизацию к кортежам?
I've found that constructing a list beats constructing a tuple on Python 3.14. For my computer, this begins at roughly ~20 elements.
That seems rather intriguing. What made this possible? Could tuples receive that optimization as well?
Можете привести побольше подробностей, включая сам код теста (списки и кортежи можно создавать разными способами), метод измерения и полученные цифры? А в более ранних версиях Python было иначе?
Я и сам исследовал похожий вопрос, сравнивая следующие четыре варианта:
1. list(values)
2. [*values]
3. tuple(values)
4. (*values,)
Если я правильно помню, 2 обгонял 1, а 3 обгонял 4, что казалось странным. Уже забыл, к какому выводу тогда пришёл…
Would you provide some more specifics, including your actual benchmark code (lists and tuples can each be constructed several ways), the measurement method and the figures you got? Were older Python releases different, too?
I've investigated a similar question myself, looking at these four alternatives:
1. list(values)
2. [*values]
3. tuple(values)
4. (*values,)
As I recoll, 2 beat 1, whereas 3 beat 4, which seemed strange. I've forgotten what conclusion I reached there…
Только что повторил измерение с values = itertools.repeat(None, 2**20):
4.02 ± 0.04 ms list(values)
3.97 ± 0.03 ms [*values]
4.76 ± 0.08 ms tuple(values)
7.91 ± 0.12 ms (*values,)
Python: 3.13.0 (main, Nov 12 2025, 14:27:38) [GCC 15.2.1 20250820]
скрипт
from timeit import timeit
from statistics import mean, stdev
import random
import sys
prelude = """
from itertools import repeat
values = repeat(None, 2**20)
"""
expressions = ['list(values)', '[*values]',
'tuple(values)', '(*values,)']
samples = {expression: [] for expression in expressions}
for trial in range(120):
for expression in random.sample(expressions, len(expressions)):
elapsed = timeit(expression, prelude, number=1)
samples[expression].append(elapsed)
for expression in expressions:
fastest = [elapsed * 1e3 for elapsed in sorted(samples[expression])[:6]]
print(f'{mean(fastest):5.2f} ± {stdev(fastest):3.2f} ms ', expression)
print('\nPython:', sys.version)
Запустить этот пример!
(Преимущество [*values] перед list(values) относилось к коротким итерируемым объектам, поскольку интерпретатор обрабатывает [*values] непосредственно как синтаксическую конструкцию.)
В общем, смутно припоминаю, что создание кортежей оптимизировали для коротких вариантов, ведь обычно используют именно их. Если нужно хранить много объектов, обычно берут список, а не большой кортеж. Оптимизация для небольшого входа вполне может замедлить обработку большого.
I've just repeated the test using values = itertools.repeat(None, 2**20):
4.02 ± 0.04 ms list(values)
3.97 ± 0.03 ms [*values]
4.76 ± 0.08 ms tuple(values)
7.91 ± 0.12 ms (*values,)
Python: 3.13.0 (main, Nov 12 2025, 14:27:38) [GCC 15.2.1 20250820]
script
from timeit import timeit
from statistics import mean, stdev
import random
import sys
prelude = """
from itertools import repeat
values = repeat(None, 2**20)
"""
expressions = ['list(values)', '[*values]',
'tuple(values)', '(*values,)']
samples = {expression: [] for expression in expressions}
for trial in range(120):
for expression in random.sample(expressions, len(expressions)):
elapsed = timeit(expression, prelude, number=1)
samples[expression].append(elapsed)
for expression in expressions:
fastest = [elapsed * 1e3 for elapsed in sorted(samples[expression])[:6]]
print(f'{mean(fastest):5.2f} ± {stdev(fastest):3.2f} ms ', expression)
print('\nPython:', sys.version)
Run This Example!
(The advantage of [*values] over list(values) applied to small iterables, since the interpreter can process [*values] directly as syntax.)
Regardless, my hazy recollection is that constructing tuples favors small ones, since those are what people typically need. Generally you'd choose a list rather than fill a tuple with lots of objects. Improving the small-input case can also make larger inputs slower.
Всем привет, Я новичок в разработке компилятора Rust и сейчас пробую реализовывать оптимизации компилятора. Может кто-нибудь…