Если вас беспокоит, что 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"
печать
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 and b and c
. (Если функции объединены или объединены, вместо них используйте any
встроенный.)