Заметил забавный факт и никак не могу понять в чем дело. any / all работают медленнее чем такой же самописный цикл. Для примера возьмем задачу: проверить, подходит ли строка под шаблон '[a-Z_]\w+'. Те является ли она корректным именем переменной.
#!/usr/bin/env python3
import re
import string
regexp1 = re.compile(r'^[a-z_]\w*$', re.IGNORECASE)
symbols = frozenset(string.ascii_letters + string.digits + '_')
def check1(name):
return regexp1.search(name) is not None
def check2(name):
first_ch = name[0]
if first_ch >= '0' and first_ch <= '9':
return False
for ch in name:
if ch not in symbols:
return False
return True
def check3(name):
first_ch = name[0]
if first_ch >= '0' and first_ch <= '9':
return False
return all(ch in symbols for ch in name)
def check_speed(fname, name, count):
from timeit import timeit
time = timeit('{0}("{1}")'.format(fname, name), 'from __main__ import {0}'.format(fname), number=count)
print('{0}: {1:.3f} seconds in {2} iterations for "{3}"'.format(fname, time, count, name))
def main():
import sys
fnames = ['check1', 'check2', 'check3']
name = sys.argv[1]
count = int(sys.argv[2])
for fname in fnames:
check_speed(fname, name, count)
if __name__ == '__main__':
main()
При этом получаем интересные результаты, на фоне которых интересно выделяется отставание примера с all
[actics@6910p trash]$ ./p.py "a12" 1000000
check1: 4.822 seconds in 1000000 iterations
check2: 2.143 seconds in 1000000 iterations
check3: 4.985 seconds in 1000000 iterations
[actics@6910p trash]$ ./p.py "a12345678901234567890" 1000000
check1: 6.784 seconds in 1000000 iterations
check2: 5.328 seconds in 1000000 iterations
check3: 10.320 seconds in 1000000 iterations
[actics@6910p trash]$ ./p.py "a12345678901234567890123456789012345678901234567890" 1000000
check1: 9.881 seconds in 1000000 iterations
check2: 11.759 seconds in 1000000 iterations
check3: 19.880 seconds in 1000000 iterations
Результаты для первого и второго теста очевидны: чем больше вход тем меньше сказываются накладные расходы на инициализацию автомата в регекспе, поэтому check1 начинает уделывать check2. А вот результаты с all мне абсолютно не понятны: в чем может быть дело? В использовании генератора? Проверил, если передавать массив набитый булами all начинает ускоряться. Получается, что с генераторами лучше велосипедить цикл? Или дело в чем-то другом?