si lo hago:¿Reduce() el cortocircuito de Python?
result = reduce(operator.and_, [False] * 1000)
se detendrá después de que el primer resultado? (Ya que False & anything == False
)
mismo modo:
result = reduce(operator.or_, [True] * 1000)
si lo hago:¿Reduce() el cortocircuito de Python?
result = reduce(operator.and_, [False] * 1000)
se detendrá después de que el primer resultado? (Ya que False & anything == False
)
mismo modo:
result = reduce(operator.or_, [True] * 1000)
No lo hace. Su alternativa en este caso es any y all.
result = reduce(operator.and_, [False] * 1000)
result = reduce(operator.or_, [True] * 1000)
pueden ser reemplazados por
result = all([False] * 1000)
result = any([True] * 1000)
que hacer cortocircuito.
Los resultados de temporización mostrar la diferencia:
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
no sólo reduce() no cortocircuito, no puede posiblemente cortocircuito sobre todos los artículos que se reduce, ya que sólo considera los elementos de dos en dos un momento. Además, no tiene idea de las condiciones bajo las cuales la función que se usa está en cortocircuito. (Sería ingenioso que las funciones pudieran tener una propiedad que indique el valor al que comienzan a cortocircuitarse, lo que reduce() podría reconocer y usar, pero no).
Es por eso que a los usuarios de Lisp les encanta Lisp, porque todas las funciones son datos, es (en principio) posible hacer este tipo de detección. – Lucretiel
Puede ser posible (ver fate of reduce) que una implementación alternativa hará un buen trabajo.
Esta idea me ha funcionado perfectamente para hacer las cosas más transparentes en el diseño.
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)
Como se ve reducir se divide en iApply < - ipairs.
Tenga en cuenta que no es equivalente a
def ireduce(seq, func):
prev = None
for item in seq:
if prev is None:
prev = item
else:
prev = func(prev, item)
return prev
Tenga en cuenta que la evaluación de cortocircuito no es siempre lo que quiere. "Fijar" reducir al cortocircuito sería un error por esa razón. Por ejemplo, recientemente tuve que cambiar mi uso de todo() para reducir() mientras procesaba una lista de formularios en django: deseo informar cualquier problema is_valid(), no solo el primero.
podría usar un argumento de palabra clave para los criterios de cortocircuito, otras instrucciones de uso do: reduce (operator.or, mylist, key = lambda x:: x <0) – LBarret
Tienes razón. 'any()' y 'all()' parecen ser exactamente lo que necesito (y probablemente también más claro). ¿Cómo hiciste ese tiempo? –
Estoy usando 'ipython' y su comando' timeit'. Pero Python tiene un módulo timeit. Entonces puede hacer 'python -mtimeit 'result = any ([True] * 10)' 'desde la línea de comando para medir el tiempo. –