По прихоти, я недавно проверил эти два метода с помощью timeit
, чтобы узнать, какой метод оценки был быстрее:
import timeit
"""Test method returns True if either argument is falsey, else False."""
def and_chk((a, b)):
if not (a and b):
return True
return False
def not_or_chk((a, b)):
if not a or not b:
return True
return False
... и получили следующие результаты:
VALUES FOR a,b -> 0,0 0,1 1,0 1,1
method
and_chk(a,b) 0.95559 0.98646 0.95138 0.98788
not_or_chk(a,b) 0.96804 1.07323 0.96015 1.05874
...seconds per 1,111,111 cycles.
Разница в эффективности составляет от одного до девяти процентов, всегда в пользу if not (a and b)
, что противоположно тому, что я мог ожидать, так как я понимаю, что if not a or not b
будет оценивать свои термины (if not a
, а затем if not b
) в порядке, запустив блок if
, когда он встречает истинное выражение (и нет предложений and
). Напротив, метод and_chk
должен оценивать оба предложения, прежде чем он сможет вернуть любой результат в if not..
, который его обертывает.
Результаты синхронизации, однако, опровергают это понимание. Как же оценивается условие if
? Я прекрасно понимаю, что эта степень микрооптимизации практически, если не полностью, бессмысленна. Я просто хочу понять, как это происходит с Python.
Для завершения сакэ, вот как я установил timeit
...
cyc = 1111111
bothFalse_and = iter([(0,0)] * cyc)
zeroTrue_and = iter([(1,0)] * cyc)
oneTrue_and = iter([(0,1)] * cyc)
bothTrue_and = iter([(1,1)] * cyc)
bothFalse_notor = iter([(0,0)] * cyc)
zeroTrue_notor = iter([(1,0)] * cyc)
oneTrue_notor = iter([(0,1)] * cyc)
bothTrue_notor = iter([(1,1)] * cyc)
time_bothFalse_and = timeit.Timer('and_chk(next(tups))', 'from __main__ import bothFalse_and as tups, and_chk')
time_zeroTrue_and = timeit.Timer('and_chk(next(tups))', 'from __main__ import zeroTrue_and as tups, and_chk')
time_oneTrue_and = timeit.Timer('and_chk(next(tups))', 'from __main__ import oneTrue_and as tups, and_chk')
time_bothTrue_and = timeit.Timer('and_chk(next(tups))', 'from __main__ import bothTrue_and as tups, and_chk')
time_bothFalse_notor = timeit.Timer('not_or_chk(next(tups))', 'from __main__ import bothFalse_notor as tups, not_or_chk')
time_zeroTrue_notor = timeit.Timer('not_or_chk(next(tups))', 'from __main__ import zeroTrue_notor as tups, not_or_chk')
time_oneTrue_notor = timeit.Timer('not_or_chk(next(tups))', 'from __main__ import oneTrue_notor as tups, not_or_chk')
time_bothTrue_notor = timeit.Timer('not_or_chk(next(tups))', 'from __main__ import bothTrue_notor as tups, not_or_chk')
... затем выполнил каждую функцию timeit.Timer(..)
с помощью .timeit(cyc)
, чтобы опубликовать результаты.