Как выясняется, в Python не все операторы созданы одинаково.
Вы упоминаете "тактовый цикл" в своем вопросе. Это правда, что типичный ЦП может выполнять многие из этих задач за один цикл, однако выполнение кода Python (в CPython) определяется скомпилированным байт-кодом. Это список операций (кодов операций), которые отображаются на код C во время выполнения CPython.
Время выполнения этих частей кода C, очевидно, может отличаться. Фактически, вы обнаружите, что ни одна из них не ассоциируется с операцией «1 цикла», а скорее с несколькими вызовами функций и операторами ветвления.
Если вы разберете две заданные вами функции, dis.dis(parity)
, вы в соответствующем разделе вы увидите, как отличаются их коды операций.
От первой функции (отрицание)
10 LOAD_FAST 1 (p)
12 UNARY_INVERT
14 STORE_FAST 1 (p)
От второй функции (XOR):
10 LOAD_FAST 1 (p)
12 LOAD_CONST 2 (1)
14 BINARY_XOR
16 STORE_FAST 1 (p)
В частности, UNARY_INVERT
изменяется на BINARY_XOR
. Проверьте мастер switch (opcode) { ... }
в Python / ceval. c, чтобы увидеть, как эти операционные коды и соответствующий им код отличаются.
Вот небольшая тестовая программа для сравнения времени некоторых различных операторов в Python.
import timeit
print('binary operators')
ops = ['+', '-', '^', '&', '|']
for op in ops:
t = timeit.timeit(f'a = a {op} b', 'a = 1; b = 2')
print(op, t)
print('unary operators')
ops = ['-', '~', 'not']
for op in ops:
t = timeit.timeit(f'a = {op} a', 'a = 1')
print(op, t)
Вот мои результаты в CPython 3.7.2 64 бит (Windows)
binary operators
+ 0.038782999999999956
- 0.03799190000000002
^ 0.05287609999999998
& 0.03716779999999997
| 0.0518267
unary operators
- 0.020763399999999987
~ 0.020213900000000007
not 0.01701140000000001
Из этих результаты, кажется, ^
или BINARY_XOR
на самом деле самый медленный оператор (из протестированных)