Почему троичный оператор более эффективен в python, чем if-else?
Исследуя некоторый код на python, я пришел к странному выводу, что и if-else, и троичные условные операторы в python приведут к одинаковому количеству исполняемых инструкций байт-кода, однако оператор If-Else будет немного медленнее.
Давайте рассмотрим этот пример функции:
def test(foo):
bar = 0
if (foo > 0):
bar = 1
else:
bar = 0
return bar
После разборки его байт-код выглядит так:
7 0 LOAD_CONST 1 (0)
3 STORE_FAST 1 (bar)
8 6 LOAD_FAST 0 (foo)
9 LOAD_CONST 1 (0)
12 COMPARE_OP 4 (>)
15 POP_JUMP_IF_FALSE 27
9 18 LOAD_CONST 2 (1)
21 STORE_FAST 1 (bar)
24 JUMP_FORWARD 6 (to 33)
11 >> 27 LOAD_CONST 1 (0)
30 STORE_FAST 1 (bar)
12 >> 33 LOAD_FAST 1 (bar)
36 RETURN_VALUE
Теперь давайте заменим оператор if-else на тернарный оператор, то есть:
def test(foo):
bar = 0
bar = 1 if foo > 0 else 0
return bar
Тогда байт-код выглядит следующим образом:
7 0 LOAD_CONST 1 (0)
3 STORE_FAST 1 (bar)
8 6 LOAD_FAST 0 (foo)
9 LOAD_CONST 1 (0)
12 COMPARE_OP 4 (>)
15 POP_JUMP_IF_FALSE 24
18 LOAD_CONST 2 (1)
21 JUMP_FORWARD 3 (to 27)
>> 24 LOAD_CONST 1 (0)
>> 27 STORE_FAST 1 (bar)
9 30 LOAD_FAST 1 (bar)
33 RETURN_VALUE
Итак, вот разница между 2-мя байтовыми кодами:
Условный оператор
goto .end1 if foo < 0
store 1 in register
store register to bar
goto .end2
.end1
store 0 in register
store register to bar
.end2:
push bar
return
Тернарный оператор
goto .end1 if foo < 0
store 1 in register
goto .end2
.end1
store 0 in register
.end2:
store register to bar
push bar
return
Затем в любом случае обе реализации должны выполнить одинаковое количество операций (11, если условие истинно, 10, если оно ложно).
Однако троичный оператор, по-видимому, значительно быстрее, чем оператор if-else. Я запустил эту функцию 1 миллиард раз, и вот результаты:
- Утверждение If-Else: 147 секунд
- Тернарный оператор: 136 секунд
Я что-то пропустил?
Код, используемый для измерения времени выполнения:
import time
size = 1000000000
t0 = time.time()
for k in range(size):
test(k)
print(time.time() - t0)
Окружение: Python3
ОС: Linux Slackware64 14,2