Favorite non-python language trick?

Christopher Subich spam.csubich+block at block.subich.spam.com
Sat Jul 2 22:28:53 EDT 2005


Steven D'Aprano wrote:
> On Fri, 01 Jul 2005 12:24:44 -0700, Devan L wrote:
> 
> 
>>With the exception of reduce(lambda x,y:x*y, sequence), reduce can be
>>replaced with sum, and Guido wants to add a product function.
> 
> 
> How do you replace:
> 
> reduce(lambda x,y: x*y-1/y, sequence) 
> 
> with sum?

You don't, but an almost equally short replacement works just as well, 
and doesn't even need the lambda:
 >>>sequence=range(1,100)
 >>>_res = 0.0
 >>>for x in sequence: _res = _res*x + 1/x
 >>><blank line if in interactive mode>
 >>>_res
9.3326215443944096e+155

Sure, this isn't a sum, but I'd argue that the for loop solution is 
superior:

1) For single expressions, the guts of the operation is still a single line
2) This completely avoids lambda -- while I myself am ambivalent about 
the idea of lambda going away, lambda syntax can get hairy for 
complicated expressions -- the comma changes meaning halfway through the 
expression, from 'parameter delimiter in lambda' to 'next parameter in 
reduce'
3) This trivially extends to a block of code, which a lambda doesn't
4) Behavior for zero- and one-length lists is explicit and obvious.

There are, of course, a few disadvantages, but I think they're more 
corner corner cases.
1) This solution obviously isn't itself an expression (although the 
result is a single variable), so it can't be used in totality as a 
component to a larger call.
[Rebuttal: When exactly would this be a good thing, anyway? Reduce 
statements are at least 11 characters long, 13 with a one-character 
default value.  Using this as a parameter to just about anything else, 
even a function call, seems a bit unreadable to me.]
2) An explicit intermediate/result value is needed.  This seems to be 
more of a 'cleanliness' argument than anything.

Besides, rewriting this as a for loop actually improves performance:
 >>> sequence = range(1,100)
 >>> def f1():
	j = 0.0
	for x in sequence: j = j*x+1/x
	return j

 >>> def f2():
	return reduce(lambda x,y: x*y - 1/y, sequence)
 >>> def runtime(f,n):
	starttime = time.time()
	for i in xrange(n):
		f()
	print time.time()-starttime
 >>> runtime(f1,10000)
1.37199997902
 >>> runtime(f2,10000)
3.67499995232

Making the series bigger results in even worse relative performance (no 
idea why):
 >>> sequence = range(1,1000)
 >>> runtime(f1,10000)
18.4169998169
 >>> runtime(f2,10000)
125.491000175

So really, 'reduce' is already useless for large anonymous blocks of 
code (which can't be defined in lambdas), and it seems slower than 'for 
.. in' for even simple expressions.



More information about the Python-list mailing list