因为Python需要完成更多的工作,所以你的第一个版本需要更长时间来运行。
当使用CPython(从python.org下载或在计算机上找到的python或python3可执行文件)时,你的Python代码被编译成字节码,然后核心评估循环依次执行每个字节码。该大循环是由C实现并编译为适合特定操作系统和CPU架构的机器代码。内置的int和str类型也完全由C代码实现,包括当你在它们上面使用[...]索引或使用运算符时运行的代码。
那么是什么导致一个版本快而另一个版本慢呢?关键是用C代码执行的操作的相对速度与使用许多Python代码(转换为字节码)执行相同操作的速度。
dis
模块可以显示生成的字节码(以人类可读的形式表示)。下面是你的第一个函数的字节码:
>>> import dis
>>> dis.dis(is_palindrome)
6 0 LOAD_CONST 1 (0)
2 STORE_FAST 1 (result)
7 4 LOAD_FAST 0 (n)
6 STORE_FAST 2 (temp)
8 >> 8 LOAD_FAST 2 (temp)
10 LOAD_CONST 1 (0)
12 COMPARE_OP 4 (>)
14 POP_JUMP_IF_FALSE 46
9 16 LOAD_FAST 1 (result)
18 LOAD_CONST 2 (10)
20 INPLACE_MULTIPLY
22 STORE_FAST 1 (result)
10 24 LOAD_FAST 1 (result)
26 LOAD_FAST 2 (temp)
28 LOAD_CONST 2 (10)
30 BINARY_MODULO
32 INPLACE_ADD
34 STORE_FAST 1 (result)
11 36 LOAD_FAST 2 (temp)
38 LOAD_CONST 2 (10)
40 INPLACE_FLOOR_DIVIDE
42 STORE_FAST 2 (temp)
44 JUMP_ABSOLUTE 8
12 >> 46 LOAD_FAST 1 (result)
48 LOAD_FAST 0 (n)
50 COMPARE_OP 2 (==)
52 RETURN_VALUE
这是第二个:
>>> dis.dis(is_palindrome_str)
6 0 LOAD_GLOBAL 0 (int)
2 LOAD_GLOBAL 1 (str)
4 LOAD_FAST 0 (n)
6 CALL_FUNCTION 1
8 LOAD_CONST 1 (None)
10 LOAD_CONST 1 (None)
12 LOAD_CONST 2 (-1)
14 BUILD_SLICE 3
16 BINARY_SUBSCR
18 CALL_FUNCTION 1
20 LOAD_FAST 0 (n)
22 COMPARE_OP 2 (==)
24 RETURN_VALUE
你不需要理解这些输出中每个字节码的效果,但是你可以看到其中一个列表要大得多。
因此,int(str(number)[::-1])
也做了很多工作,但它更快,因为这项工作是在本地代码中完成的,而本地代码比必须处理所有可能的字节码操作的大循环更有效率。
对于非常大的数字,编写一个从外向内工作并尽早退出的循环可能更有效(从math.log10(...)
中获取数字的幅度,将其与1配对,并一步步地朝中间前进进行测试,在获得False
结果时返回),但即使是这种情况,字符串转换也可能会获胜。
我唯一能提供的 小 改进是您 不需要 转换回 int()
:
def is_palindrome_str_faster(n):
return (v := str(n)) == v[::-1]
以上 (ab) 使用了 Python 3 的赋值表达式语法。您还可以将其编写为:
def is_palindrome_str_faster(n):
v = str(n)
return v == v[::-1]
几乎没有字节码或性能方面的区别。
使用timeit
模块比较这些方法:
>>> timeit('ip(12345654321)', 'from __main__ import is_palindrome as ip')
1.8687424899544567
>>> timeit('ip(12345654321)', 'from __main__ import is_palindrome_str as ip')
0.5467583388090134
>>> timeit('ip(12345654321)', 'from __main__ import is_palindrome_str_faster as ip')
0.42572025093249977
str()
、[::-1]
和int()
函数可以被您的 CPU 更快地执行。 - Martijn Pieters