[Python-ideas] Add nullifier argument to functools.reduce?

Steven D'Aprano steve at pearwood.info
Sun Aug 24 03:53:26 CEST 2014


On Sat, Aug 23, 2014 at 11:43:42AM -0700, David Mertz wrote:

>   def reduce_with_attractor(func, it, start=None, end_if=None):
>       it = iter(it)
>       start = start if start!=None else it.__next__()
>       return list(takewhile(lambda x: x!=end_if,
>                             accumulate(chain([start],it), func)))[-1]

A couple of points:

- Don't use it.__next__(), use the built-in next(it).

- To match the behaviour of reduce, you need to catch the StopIteration 
and raise TypeError.

- Your implementation eagerly generates a potentially enormous list of 
intermediate results, which strikes me as somewhat unfortunate for a 
functional tool like reduce. In other words, for some inputs, this is 
going to perform like a dog, generating a HUGE list up front, then 
throwing it all away except for the final value.

 
> This gives you the accumulation up-to-but-not-including the attractor.  I
> guess the OP wanted to return the attractor itself (although that seems
> slightly less useful to me).

Not really. His use-case seems to be to short-cut a lot of unnecessary 
calculations, e.g. suppose you write product() as reduce(operator.mul, 
iterable). In the event that the product reaches zero, you can[1] 
short-circuit the rest of the iterable and just return 0:

product([1, 2, 3, 0] + [4]*1000000)

ought to reduce 0, not 6, and the intent is for it to do so *quickly*, 
ignoring the 4s at the end of the list.




[1] Actually you can't. 0 is no longer an attractor in the presence of 
INF or NAN.



-- 
Steven


More information about the Python-ideas mailing list