I wonder why there aren't more people advocating the use of these functions in Python programs instead of for loops.
I wonder why there aren't more people advocating the use of these functions in Python programs instead of for loops.
For example, I have nothing against the code like this:
if any(foo.is_cond for foo in foos):
do(bar)
but I cringe when I see `import functools, operator`, `reduce` or complex nested list comprehensions.It may work better in ML-derived functional languages because function definitions there, both anonymous and named, are extremely lightweight. This part of the language is highly optimized by necessity as high order functions is the only way to express iteration and other control flow constructs. But in Python, though not particularly heavyweight, function definitions don't mix well with regular code.
Also I'm not sure if the author is completely fair with his loop example. Add a few local variables, `break` or `continue`, and the high order form may actually become less intuitive.
Honestly, I suspect the Haskell style and the curious Python cultural disdain for real lambadas have far more to do with your confort than any absolute metric of comprehension.
(Nitpicking forever!)
Python's reduce function has an optional starting value argument: http://docs.python.org/library/functions.html#reduce
For-loops are still suitable for actions (which mutate state or for some other reason need to be evaluated in order) - you see this in Haskell, too, though, with Control.Monad's forM_ and the like.
sum([ range(n,n+5) for n in range(5) ])
just gave me "TypeError: unsupported operand type(s) for +: 'int' and 'list'", which didn't make a lot of sense. Where did I pass an 'int' by itself? Well, according to the help, sum takes a second argument: a starting value, which defaults to 0. So, I wondered, what if I were to pass it an empty list...? sum([ range(n,n+5) for n in range(5) ], [])
came back with: [0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8]
Holy $#!7I'd been wanting a way to join multiple lists without having to write another ugly little function! Anyone know if this particular trick is common practice?
The help says as much, in fact. Actually, what it says is, "Returns the sum of a sequence of numbers (NOT strings)," which I think is meant to imply it won't parse numbers out of strings, but in theory, sum should be able to concatenate strings as easily as it does lists, with the right start argument. Instead:
>>> sum([['room315'], ['room2']], [])
['room315', 'room2']
but: >>> sum(['room315', 'room2'], '')
TypeError: sum() can't sum strings [use ''.join(seq) instead]
Say, what???I'm not sure, but I think sum is specifically watching for strings, and throwing a TypeError if it finds one. Otherwise, if it's simply using the + operator internally, as its list-handling behabior seems to imply, it should mash strings together just as happily! Oh, well. The join function is the right one for that job. It just seems a bit of wasted effort, to me.
A more efficient version would be: def sumseq(l): r = []; map(r.extend,l); return r
which would also work on any type of sequence as input, even if mixed. A quick test shows the quadratic time complexity being noticeable at about 128 items, where sumseq is 10x as fast and 1751x as fast at 16384 items.
I'm usually only reading and not writing python but I think list comprehensions are more idiomatic. Based on some comments I've seen here I also kind of get the impression comprhensions are abused.
The latter is a different thing..
We prefer the terms:
"brother by a different mother"
or if they're being naughty:
"red headed step-child".