Не go по впечатлениям. Тест!
Фокус на строковой операции:
In [46]: vocab = 'abcdefghijklmnopqrstuvwxyz ,-'
In [47]: ind = np.random.randint(0, len(vocab), size=10000)
...:
In [48]: s = ''.join(vocab[i] for i in ind)
In [49]: len(s)
Out[49]: 10000
Ваш тестовый пример:
In [50]: timeit s = ''.join(vocab[i] for i in ind)
1.9 ms ± 2.14 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
итерация в списке быстрее, чем итерация в массиве:
In [51]: timeit s = ''.join(vocab[i] for i in ind.tolist())
1.06 ms ± 19.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [52]: %%timeit ind1=ind.tolist()
...: s = ''.join(vocab[i] for i in ind1)
...:
906 µs ± 511 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
То же самое для l oop немного медленнее:
In [53]: %%timeit ind1=ind.tolist()
...: alist = []
...: for i in ind1:
...: alist.append(vocab[i])
...: ''.join(alist)
.
1.09 ms ± 372 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Понимание списка может дать более чистый и читаемый код, но это не a основной инструмент скорости. В этом случае vocab[i]
все еще выполняется каждый раз. Нет компиляции.
===
Использование понимания списка вместо выражения генератора сокращает время:
In [54]: %%timeit ind1=ind.tolist()
...: s = ''.join([vocab[i] for i in ind1])
...:
641 µs ± 58.7 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
generators
хороши, если они кормят больше генераторы в серии, но сами по себе мало что делают.