我需要检查字符串是否为十六进制。我学会了2种方法-
1。)遍历每个字符
all(c in string.hexdigits for c in s) # Straight forward with no optimizations
2。)使用int()函数检查错误
try:
int(s, 16)
return True
except ValueError:
return False
在第一种情况下,我知道复杂度为O(n)。但是第二个呢?那里的时间复杂度是多少?
int(s, 16)
仍将具有复杂度O(n),其中n == len(s)
,但两者不能直接比较。 int
将以比all
更低的级别遍历数据,这速度更快,但是int
也会做更多的工作(它实际上必须计算s
的整数值)。
那么哪个更快?您必须同时配置两者。
In [1]: s = "783c"
In [2]: import string
In [3]: %timeit all(c in string.hexdigits for c in s)
800 ns ± 3.23 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [4]: %%timeit
...: try:
...: int(s, 16)
...: except ValueError:
...: pass
...:
223 ns ± 1.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
看起来像是内部迭代胜出。我也对9位数字的字符串进行了测试,int
仍然快4倍。
但是invalid字符串呢?
In [8]: s = 'g'
In [9]: %%timeit
...: try:
...: int(s, 16)
...: except ValueError:
...: pass
...:
1.09 µs ± 2.62 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [10]: %timeit all(c in string.hexdigits for c in s)
580 ns ± 6.55 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
现在,我们基本上正在测试短路带来的好处与捕获异常的代价。如果错误稍后出现在字符串中,该怎么办?
In [11]: s = "738ab89ffg"
In [12]: %timeit all(c in string.hexdigits for c in s)
1.59 µs ± 19.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [13]: %%timeit
...: try:
...: int(s, 16)
...: except ValueError:
...: pass
...:
1.25 µs ± 19.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
现在,我们再次看到内部迭代的好处。