Очевидная пауза между каждым циклом вызвана интерполятором , который по умолчанию использует Interpolator.EASE_BOTH
(поэтому он замедляется в конце каждого цикла и ускоряется в начале).
Чтобы удалить это, просто установите интерполятор на Interpolator.LINEAR
:
rotateTransition.setInterpolator(Interpolator.LINEAR);
операторы if
будут пропускать все в скобках else
, если оно имеет значение true. Следует отметить, что беспокойство по поводу такого рода проблем, если это не делается миллионы раз за выполнение программы, называется «преждевременной оптимизацией», и ее следует избегать. Если ваш код более понятен с тремя операторами if (a и b и c)
, их следует оставить внутри.
Только, чтобы сказать, что конструкция
if a:
if b:
if c:
else: #note A
if c:
else:
if b:
if c:
else: #note A
if c:
не хорошо создается. в" (a и b и c)" создают интерпретатор (и большая часть скомпилированного кода Ленга) просто игнорируют условия после ложного значения, таким образом, "#note" еще ответвление не было должно существовать. Запись (a и b и c) делает это неявно.
if (a и b и c)
завершится ошибкой, если a
является ложным, и не потрудиться проверить b
или c
.
Тем не менее, я лично считаю, что вложенные условные выражения легче читать, чем комбинации условных выражений 2 ^ n.
В общем, если вы хотите определить, какой способ сделать что-то наиболее быстрый, вы можете написать простой тест, используя timeit .
if (a, b и c)
быстрее и лучше, ради «оптимизации кода настоящего программиста» и читабельности кода.
Я бы сказал, что единый тест работает так же быстро, как и отдельные тесты. В Python также используется так называемая оценка замыкания.
Это означает для (a и b и c)
, что b
или c
больше не будут проверяться, если a
будет false
.
Аналогично, если у вас есть выражение OR
(a или b)
и a
является true
, b
никогда не будет оценено.
Итак, подведем итог: клаузулы не проваливаются быстрее с разделением.
Код:
import dis
def foo():
if ( a and b and c):
pass
else:
pass
def bar():
if a:
if b:
if c:
pass
print 'foo():'
dis.dis(foo)
print 'bar():'
dis.dis(bar)
Вывод:
foo():
4 0 LOAD_GLOBAL 0 (a)
3 JUMP_IF_FALSE 18 (to 24)
6 POP_TOP
7 LOAD_GLOBAL 1 (b)
10 JUMP_IF_FALSE 11 (to 24)
13 POP_TOP
14 LOAD_GLOBAL 2 (c)
17 JUMP_IF_FALSE 4 (to 24)
20 POP_TOP
5 21 JUMP_FORWARD 1 (to 25)
>> 24 POP_TOP
7 >> 25 LOAD_CONST 0 (None)
28 RETURN_VALUE
bar():
10 0 LOAD_GLOBAL 0 (a)
3 JUMP_IF_FALSE 26 (to 32)
6 POP_TOP
11 7 LOAD_GLOBAL 1 (b)
10 JUMP_IF_FALSE 15 (to 28)
13 POP_TOP
12 14 LOAD_GLOBAL 2 (c)
17 JUMP_IF_FALSE 4 (to 24)
20 POP_TOP
13 21 JUMP_ABSOLUTE 29
>> 24 POP_TOP
25 JUMP_ABSOLUTE 33
>> 28 POP_TOP
>> 29 JUMP_FORWARD 1 (to 33)
>> 32 POP_TOP
>> 33 LOAD_CONST 0 (None)
36 RETURN_VALUE
Итак, хотя установка та же, очистка комбинированного выражения происходит быстрее, так как в стеке остается только одно значение.
По крайней мере, в python эффективность уступает удобочитаемости, и «плоский лучше, чем вложенный».
См. Дзен Python
Я сомневаюсь, что вы заметите заметную разницу, поэтому рекомендую сделать все, что делает код наиболее читаемым.
Если вас беспокоит, что b или c - это функции, которые вызываются, а не просто переменные, которые оцениваются, то этот код показывает, что замыкание - ваш друг:
a = False
def b():
print "b was called"
return True
if a and b():
print "this shouldn't happen"
else:
print "if b was not called, then short-circuiting works"
prints
if b was not called, then short-circuiting works
Но если у вас есть код, который делает это:
a = call_to_expensive_function_A()
b = call_to_expensive_function_B()
c = call_to_expensive_function_C()
if a and b and c:
do something...
то ваш код все равно вызывает все 3 дорогие функции. Лучше позволить Python быть Python:
if (call_to_expensive_function_A() and
call_to_expensive_function_B() and
call_to_expensive_function_C())
do something...
который будет вызывать только столько дорогих функций, сколько необходимо для определения общего состояния.
Редактировать
Вы можете обобщить это, используя all
встроенный:
# note, this is a list of the functions themselves
# the functions are *not* called when creating this list
funcs = [function_A, function_B, function_C]
if all(fn() for fn in funcs):
do something
Теперь, если вам нужно добавить другие функции или изменить их порядок (возможно, function_A
отнимает много времени, и вы выиграете, отфильтровав случаи, которые сначала не выполнят function_B
или function_C
), вы просто обновите список funcs
. all
выполняет замыкание так же, как если бы вы прописали if как if a и b и c
. (Если функции 'or'ed вместе, используйте вместо этого встроенный модуль any
)