re
appears to be quite fast:
import re
# to check whether any outside ranges (->MatchObject) / all in ranges (->None)
nonletter = re.compile('[^a-zA-Z]').search
# to check whether any in ranges (->MatchObject) / all outside ranges (->None)
letter = re.compile('[a-zA-Z]').search
bool(nonletter(myString1))
# True
bool(nonletter(myString2))
# True
bool(nonletter(myString2[:-1]))
# False
Benchmarks for OP's two examples and a positive one (set is @schwobaseggl setset is @DanielSanchez):
Австрия
re 0.48832818 ± 0.09022105 µs
set 0.58745548 ± 0.01759877 µs
setset 0.81759223 ± 0.03595184 µs
AustriЯ
re 0.51960442 ± 0.01881561 µs
set 1.03043942 ± 0.02453405 µs
setset 0.54060076 ± 0.01505265 µs
tralala
re 0.27832978 ± 0.01462306 µs
set 0.88285526 ± 0.03792728 µs
setset 0.43238688 ± 0.01847240 µs
Benchmark code:
import types
from timeit import timeit
import re
import string
import numpy as np
def mnsd(trials):
return '{:1.8f} \u00b1 {:10.8f} \u00b5s'.format(np.mean(trials), np.std(trials))
nonletter = re.compile('[^a-zA-Z]').search
letterset = set(string.ascii_letters)
def f_re(stri):
return not nonletter(stri)
def f_set(stri):
return all(x in letterset for x in stri)
def f_setset(stri):
return set(stri).issubset(letterset)
for stri in ('Австрия', 'AustriЯ', 'tralala'):
ref = f_re(stri)
print(stri)
for name, func in list(globals().items()):
if not name.startswith('f_') or not isinstance(func, types.FunctionType):
continue
try:
assert ref == func(stri)
print("{:16s}".format(name[2:]), mnsd([timeit(
'f(stri)', globals={'f':func, 'stri':stri}, number=1000) * 1000 for i in range(1000)]))
except:
print("{:16s} apparently failed".format(name[2:]))