我们如何有效地检查 Python 中的字符串是否为十六进制

How can we efficiently check if a string is hexadecimal in Python

我需要检查字符串是否为十六进制。我学到了 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 也做更多的工作(它实际上必须计算 [=18= 的整数值) ]).

那么哪个更快?您必须对两者进行分析。

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 倍。

但是无效字符串呢?

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)

现在我们又看到了内部迭代的好处。