Если я это сделаю:
result = reduce(operator.and_, [False] * 1000)
Будет ли он остановлен после первого результата? (так как False & anything == False
)
Аналогично:
result = reduce(operator.or_, [True] * 1000)
Если я это сделаю:
result = reduce(operator.and_, [False] * 1000)
Будет ли он остановлен после первого результата? (так как False & anything == False
)
Аналогично:
result = reduce(operator.or_, [True] * 1000)
Это не так. Ваша альтернатива в этом случае any и all.
result = reduce(operator.and_, [False] * 1000)
result = reduce(operator.or_, [True] * 1000)
можно заменить на
result = all([False] * 1000)
result = any([True] * 1000)
которые делают короткое замыкание.
Результаты синхронизации показывают разницу:
In [1]: import operator
In [2]: timeit result = reduce(operator.and_, [False] * 1000)
10000 loops, best of 3: 113 us per loop
In [3]: timeit result = all([False] * 1000)
100000 loops, best of 3: 5.59 us per loop
In [4]: timeit result = reduce(operator.or_, [True] * 1000)
10000 loops, best of 3: 113 us per loop
In [5]: timeit result = any([True] * 1000)
100000 loops, best of 3: 5.49 us per loop
Не только сокращает() не короткое замыкание, но и не может коротко замыкаться на всех элементах, которые уменьшаются, поскольку он учитывает только пункты по два за раз. Кроме того, он не имеет понятия об условиях, при которых функция используется в коротких замыканиях. (Было бы неплохо, если бы функции могли иметь свойство, указывающее на значение, при котором они начинают замыкаться, что reduce() может затем распознавать и использовать, но они этого не делают.)
Возможно, это возможно (см. судьба сокращения), что альтернативное сокращение реализации будет хорошо работать.
Эта идея отлично сработала для меня, чтобы сделать вещи более прозрачными в дизайне.
def ipairs(seq):
prev = None
for item in seq:
if prev is not None:
yield (prev, item)
prev = item
def iapply(seq, func):
for a, b in ipairs(seq):
yield func(a, b)
def satisfy(seq, cond):
return all(iapply(seq, cond))
def is_uniform(seq):
return satisfy(seq, lambda a, b: a == b)
Как вы видите, сокращение разбито на iapply < - ipairs.
Обратите внимание, что это не эквивалентно
def ireduce(seq, func):
prev = None
for item in seq:
if prev is None:
prev = item
else:
prev = func(prev, item)
return prev
Помните, что оценка короткого замыкания - это не всегда то, что вы хотите. По этой причине ошибка "фиксации" сократится до короткого замыкания. Например, недавно мне пришлось изменить использование функции all() для сокращения() при обработке списка форм в django: я хочу сообщить о любых проблемах is_valid(), а не только о первом.