2010-08-25 15 views

Respuesta

21

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 
+0

Tienes razón. 'any()' y 'all()' parecen ser exactamente lo que necesito (y probablemente también más claro). ¿Cómo hiciste ese tiempo? –

+1

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. –

5

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).

+0

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

3

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 
2

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.

+0

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

Cuestiones relacionadas