Поскольку вы обрабатываете слово за словом по сравнению с mystring
, наверняка мистик может использоваться как набор. Тогда просто взять пересечение между множеством, содержащим слова в mystring
и целевые группы слов:
In [370]: mystring=set(['foobar','barfoo','foo'])
In [371]: mystring.intersection(set(['foo', 'bar', 'hello']))
Out[371]: set(['foo'])
логический «или» есть члены пересечения двух множеств.
Использование набора также выполняется быстрее. Вот относительно времени по сравнению с генератором и регулярным выражением:
f1: generator to test against large string
f2: re to test against large string
f3: set intersection of two sets of words
rate/sec f2 f1 f3
f2 101,333 -- -95.0% -95.5%
f1 2,026,329 1899.7% -- -10.1%
f3 2,253,539 2123.9% 11.2% --
Таким образом, генератор и операция in
является 19x быстрее, чем регулярное выражение и множество пересечений 21x быстрее, чем регулярное выражение и 11% быстрее, чем генератор.
Вот код, который сгенерировал времени:
import re
with open('/usr/share/dict/words','r') as fin:
set_words={word.strip() for word in fin}
s_words=' '.join(set_words)
target=set(['bar','foo','hello'])
target_re = re.compile("(%s)" % ("|".join(re.escape(word) for word in target),))
gen_target=(word for word in ('bar','foo','hello'))
def f1():
""" generator to test against large string """
if any(s in s_words for s in gen_target):
return True
def f2():
""" re to test against large string """
if re.search(target_re, s_words):
return True
def f3():
""" set intersection of two sets of words """
if target.intersection(set_words):
return True
funcs=[f1,f2,f3]
legend(funcs)
cmpthese(funcs)
Спасибо. Но разве эта техника не предотвращает оптимизацию короткого замыкания? – ereOn
Это генератор, а не список. – johv
Нет. '(s в mystring для s в 'foo', 'bar', 'hello')' является выражением генератора, что означает, что он не вычисляется мгновенно в целом только по требованию. 'any()' останавливает итерацию, видя первое истинное значение, поэтому остальные никогда не будут проверяться. Прочитайте выражения генератора. – Kos