Почему этот метод тестирования на палиндромы намного медленнее?
У меня есть два разных метода тестирования на палиндром. Одним из них является следующее:
def palindrome(text):
return text == text[::-1]
Очень просто, конечно, но я предполагал, что это будет медленно, поскольку он (безусловно) должен хранить значение text[::-1]
где-то после изменения его, затем он проверяет каждый символ в обоих. Итак, я попробовал другой метод:
def palindrome_2(text):
left = 0
right = len(text) - 1
while left < right:
if text[left] != text[right]:
return False
right -= 1
left += 1
return True
Он начинается в начальной и конечной точках и проходит в центр. Насколько я могу судить, это должно быть быстрее, поскольку проверяет только [0, n // 2)
и наоборот для конца. Тем не менее, когда я использую timeit для тестирования, первым 0.32
а второй 1.34
, Зачем?
1 ответ
Я думаю, что это полезно для использования dis
чтобы взглянуть на полученный здесь байт-код:
import dis
dis.dis(palindrome)
dis.dis(palindrome_2)
Палиндром:
4 0 LOAD_FAST 0 (text)
3 LOAD_FAST 0 (text)
6 LOAD_CONST 0 (None)
9 LOAD_CONST 0 (None)
12 LOAD_CONST 2 (-1)
15 BUILD_SLICE 3
18 BINARY_SUBSCR
19 COMPARE_OP 2 (==)
22 RETURN_VALUE
Palindrome_2:
10 0 LOAD_CONST 1 (0)
3 STORE_FAST 1 (left)
11 6 LOAD_GLOBAL 0 (len)
9 LOAD_FAST 0 (text)
12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
15 LOAD_CONST 2 (1)
18 BINARY_SUBTRACT
19 STORE_FAST 2 (right)
12 22 SETUP_LOOP 60 (to 85)
>> 25 LOAD_FAST 1 (left)
28 LOAD_FAST 2 (right)
31 COMPARE_OP 0 (<)
34 POP_JUMP_IF_FALSE 84
13 37 LOAD_FAST 0 (text)
40 LOAD_FAST 1 (left)
43 BINARY_SUBSCR
44 LOAD_FAST 0 (text)
47 LOAD_FAST 2 (right)
50 BINARY_SUBSCR
51 COMPARE_OP 3 (!=)
54 POP_JUMP_IF_FALSE 61
14 57 LOAD_CONST 3 (False)
60 RETURN_VALUE
15 >> 61 LOAD_FAST 2 (right)
64 LOAD_CONST 2 (1)
67 INPLACE_SUBTRACT
68 STORE_FAST 2 (right)
16 71 LOAD_FAST 1 (left)
74 LOAD_CONST 2 (1)
77 INPLACE_ADD
78 STORE_FAST 1 (left)
81 JUMP_ABSOLUTE 25
>> 84 POP_BLOCK
17 >> 85 LOAD_CONST 4 (True)
88 RETURN_VALUE
По сути, при выполнении одинакового объема работы C-код будет быстрее, чем соответствующий Python-код. Как вы можете видеть, первый подход вызывает встроенную функцию, которая написана на быстром языке C. Вторая функция должна выполнять большую часть работы в коде Python, включая обработку накладных расходов циклической конструкции, которая будет медленнее, чем вызов C.