Yeah. Python has the functional programming features I expect of any modern language. However, I feel that Python has a lot of unneeded syntax. I always prefer apply() over * and map() and filter() over list comprehensions.
func(*args)
apply(func, args)
[func(a) for a in collection]
map(func, collection)
[a for a in collection if func(a)]
filter(func, collection)
I don't see why people use all of this special syntax.
(func(a) for a in collection)
map(func, collection)
as equivalent. If you want a list (and not a generator), you would need to do this:
[func(a) for a in collection]
list(map(func, collection))
For me, the first set (comprehensions) of notation has a more mathematical feel to it, i.e. { x^2 | x \in 0...10 }. Just replace the bar with "for" and it's almost the same thing.
I believe the documentation for `filter` even mentions that it is equivalent to the comprehension[1].
> It may just be a matter of which a person learned first.
I think this is the case, for me map is much harder to read. But I also think that comprehensions go back to math sets, so I was familiar with this even before learning any programming. Therefore comprehensions clicked immediately for me and it's by far my favourite python feature.
I learned both around the same time, but even in good functional languages like Haskell, using a comprehension for anything more than simple problems results in an unreadable mess.
map or filter are much easier to read for complex data manipulations and as a bonus, their composition rules make it easy to increase performance. For example, if you see two map functions together, you can wrap them in a compose and only map over your elements once. This isn't as immediately obvious when you're using comprehensions.
> [ manager.name for manager in set([
person.manager for person in employees
])]
?
I assume with something like set() or unique() you need to create the intermediate iterable anyway, but without it I have trouble finding an example where doing a single list comprehension wouldn't suffice.
Part that bothers me about Python is no special binding form, that is you could just do x = 3 to add x variable to my environment, and second is not-strict lexical scoping.
From other perceptive, these usually bother me when my functions are larger, and ideally functions should be small. So I take it as sign that I should probably break down my function.
And yeah, tail calls! I expect that from a modern language with functional programming features. Unfortunately it seems there are no plans to add them in Python
[(foo(a), bar(a)) for a in collection if condition(a) or alt(a)]
foo_bar = lambda x: (foo(x), bar(x))
condition_or_alt = lambda x: condition(x) or alt(x)
map(foo_bar, filter(condition_or_alt, collection))
As logic gets more complicated, wouldn't list comprehensions become easier to read straight through?
I don't see why people use all of this special syntax.
Comprehensions are one fairly easy way of thinking about sets of things, and transformations of those sets of things. It may not be your preferred way to think about them, but that doesn't mean it's unneeded or that people are wrong to prefer another way.
If you don't have the function handy and don't want to go thru the effort of making a lambda, list (set, dictionary, generator) comprehensions can be more convenient (and you can comprehend over nested lists too)