Вот еще один вариант, позволяющий избежать выполнения теста if
на каждой итерации.Он также использует randrange
, что несколько более эффективно, чем randint
.
from random import randrange
lst = [randrange(hi) for num, hi in ((5, 51), (2, 13)) for _ in range(num)]
print(lst)
типичный выход
[10, 31, 46, 25, 23, 6, 5]
Это эквивалентно
lst = []
for num, hi in ((5, 51), (2, 13)):
for _ in range(num):
lst.append(randrange(hi))
Внешний цикл выбирает num
, количество элементов в подсписке и hi
размер случайного диапазона для этого подсписка;внутренний цикл генерирует необходимое количество случайных чисел в нужном диапазоне.
FWIW, вот некоторый код timeit
, сравнивающий различные алгоритмы, которые были представлены.Он также проверяет, что они дают одинаковые результаты, когда получают одинаковое случайное начальное число.Мой простой код проверки использует eval
, поэтому он может проверять только выражения, а не операторы, поэтому он не может проверять код jpp или Abhishek;кроме того, код Numpy jpp в любом случае дает разные результаты, поскольку использует другой алгоритм заполнения.Пожалуйста, смотрите timeit
документы для информации о том, что timeit
делает и как интерпретировать результаты.
from timeit import Timer
import random
from random import randint, randrange, seed
from itertools import chain, repeat, starmap
from functools import partial
import numpy as np
imports = 'random, randint, randrange, seed, chain, repeat, starmap, partial, np'
commands = (
('Martijn', '', '[randint(0, 50 if i < 5 else 12) for i in range(7)]'),
('Martijn_partial',
'rint50 = partial(randint, 0, 50); rint12 = partial(randint, 0, 12)',
'[rint() for rint in [rint50] * 5 + [rint12] * 2]'
),
('Patrick', '', '[randint(*bounds) for bounds in [(0, 50)]*5 + [(0, 12)]*2]'),
('Patrick_chain', '',
'[randint(*bounds) for bounds in chain(repeat((0, 50), 5), repeat((0, 12), 2))]'
),
('Ralf', '', '[randint(0,50) for i in range(5)] + [randint(0,12) for i in range(2)]'),
('Abhishek', '', 'l = [random.randint(0,50) for i in range(5)];'
'l.extend([random.randint(0,12) for i in range(2)])'
),
('PM 2Ring', '', '[randrange(hi) for num, hi in ((5, 51), (2, 13)) for _ in range(num)]'),
('jpp', '', 'A = np.zeros(7); '
'A[:5] = np.random.randint(0, 20, 5); A[5:] = np.random.randint(0, 12, 2)'
),
('Tanmay jain', '',
'[random.randint(0,50) if i < 5 else random.randint(0,12) for i in range(7)]'
),
('juanpa', '', '[random.randint(a,b) for args in (((0,50) for _ in range(5)),'
'((0, 12) for _ in range(2))) for a, b in args]'
),
('juanpa_starmap', '', 'list(starmap(random.randint,'
'chain(repeat((0,50),5), repeat((0,12),2))))'
),
)
def verify():
for name, setup, cmd in commands:
if name in ('jpp', 'Abhishek'):
continue
seed(17)
if setup:
exec(setup)
print('{:16}: {}'.format(name, eval(cmd)))
print()
def time_test(loops):
timings = []
print('loops =', loops)
for name, setup, cmd in commands:
setup = 'from __main__ import ' + imports + ';' + setup
t = Timer(cmd, setup=setup)
result = sorted(t.repeat(3, loops))
timings.append((result, name))
timings.sort()
for result, name in timings:
print('{:16} : {}'.format(name, result))
verify()
time_test(5000)
типичный вывод
Martijn : [33, 26, 19, 23, 18, 2, 12]
Martijn_partial : [33, 26, 19, 23, 18, 2, 12]
Patrick : [33, 26, 19, 23, 18, 2, 12]
Patrick_chain : [33, 26, 19, 23, 18, 2, 12]
Ralf : [33, 26, 19, 23, 18, 2, 12]
PM 2Ring : [33, 26, 19, 23, 18, 2, 12]
Tanmay jain : [33, 26, 19, 23, 18, 2, 12]
juanpa : [33, 26, 19, 23, 18, 2, 12]
juanpa_starmap : [33, 26, 19, 23, 18, 2, 12]
loops = 5000
jpp : [0.23938178099342622, 0.24184146700281417, 0.3152835669970955]
PM 2Ring : [0.26918871099769603, 0.27244400099880295, 0.2916741489971173]
Patrick : [0.34155847399961203, 0.34415175200410886, 0.3531294650019845]
juanpa_starmap : [0.3417540490045212, 0.34329504700144753, 0.3438059809996048]
Martijn : [0.3509639670010074, 0.362117896998825, 0.547288200003095]
Martijn_partial : [0.3511254819968599, 0.35262946599686984, 0.39430355399963446]
Patrick_chain : [0.3541102219969616, 0.3545923809942906, 0.3555165420038975]
Tanmay jain : [0.3558294050017139, 0.5510739650053438, 0.7693202439986635]
Ralf : [0.3678122450000956, 0.44522786799643654, 0.44827762299973983]
juanpa : [0.4089203829935286, 0.41227930299646687, 0.42410747800022364]
Abhishek : [0.4811078249986167, 0.4942625819967361, 0.6255962599971099]
КакВы можете видеть, код Numpy jpp является самым быстрым.Я ожидаю, что разница в скорости была бы еще более очевидной, если бы мы генерировали более длинный список чисел.
Это время было выполнено на древней 32-битной одноядерной машине с частотой 2 ГГц, работающей на Python 3.6.0 на производной от Debian.дистрибутив.YMMV.
Здесь приведены временные параметры для создания списков (или массивов) из 50 + 20 = 70 значений в тех же диапазонах.
loops = 500
jpp : [0.025625186994147953, 0.025764200996491127, 0.03122780400008196]
PM 2Ring : [0.21989007600495825, 0.2200367909972556, 0.22065802400175016]
juanpa_starmap : [0.3094131350007956, 0.3110805670003174, 0.31563361900043674]
Patrick_chain : [0.3122365829985938, 0.31262181099737063, 0.3137894630053779]
Patrick : [0.3130071220002719, 0.31769691400404554, 0.3179219129960984]
Ralf : [0.31566168300196296, 0.3157304769993061, 0.3234770689959987]
Martijn : [0.3193310350034153, 0.3275600470005884, 0.35491854500287445]
Martijn_partial : [0.321399387998099, 0.3226969290044508, 0.32442738999816356]
Abhishek : [0.32655813400197076, 0.3363869300010265, 0.3657162370000151]
Tanmay jain : [0.32833286200184375, 0.33107244400162017, 0.39565577400207985]
juanpa : [0.35968791200139094, 0.3754627199959941, 0.3933205349967466]