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

Steven D'Aprano steve at pearwood.info
Sun Aug 24 15:09:08 CEST 2014


On Sun, Aug 24, 2014 at 02:35:57PM +0200, Peter Otten wrote:
> 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]
> 
> Wouldn't it be better to break this into a function that limits a sequence 
> and to combine that with the original reduce()?

In general, if x is an attractor, then we want to stop and return x if 
either of these two scenarios occur:

- we come across x in the input;

- or the sequence of intermediate values reaches x.

You can do the first by filtering the input stream, but not the second.

Here's a concrete example, sticking to product() where 0 is an 
attractor:

# best viewed with a fixed-width font
product([1, 2, 3, 9, 0, 8, 7, 4])
.....................^ stop here


But multiplication can underflow to zero too, and once it does, 
we likewise want to stop:

product([1e-70, 2e-71, 6e-69, 4e-68, 1e-48, 2e-71, 1e-69, 3e-70])
.....................................^ stop here


Notice that 1e-48 is not only non-zero, but it's considerably bigger 
than the other numbers in the sequence. (About 100000000000000000000 
times bigger, give or take a factor of 10.) Yet it's enough to cause the 
product to underflow to zero, after which the product will never 
shift away from zero. (Ignoring NANs and INFs.)

I'm still not convinced this belongs in the standard library, but it's a 
nice functional, er, function to add to your private library or as a 
third-party module.



-- 
Steven


More information about the Python-ideas mailing list