views:

273

answers:

6

I see what seems like a majority of Python developers on StackOverflow endorsing the use of concise functional tools like lambdas, maps, filters, etc., while others say their code is clearer and more maintainable by not using them. What is your preference?

Also, if you are a die-hard functional programmer or hardcore into OO, what other specific programming practices do you use that you think are best for your style?

Thanks in advance for your opinions!

+12  A: 

I use the features of the language that get the job done with the shortest, cleanest code possible. If that means that I have to mix the two, which I do quite often, then that's what gets done.

Ignacio Vazquez-Abrams
+7  A: 

Python has only marginal functional programming features so I would be surprised if many people would use it especially for that. For example there is no standard way to do function composition and the standard library's reduce() has been deprecated in favor of explicit loops.

Also, I don't think that map() or filter() are generally endorsed. In opposite, usually list comprehensions seem to be preferred.

sth
I like list comprehensions better too. I wonder if we'll see map() and filter() go the way of reduce().
Eric
Note that list comprehensions come from the functional world just as much as `map` and `filter`.
Mike Graham
A: 

I select Python when I'm taking on a problem that maps well to an OO solution. Python only provides a limited ability to program in a functional manner compared to full blown functional languages.

If I really want functional programming, I use Lisp.

LanceH
Ok, that's good to know. I guess I've never used a completely functional language. I will have to look into that.
Eric
Its worth noting that Lisp isn't a completely functional language any more than Python is. It does, however support functional programming "better" than Python (for some definition of better), much the same way that Python supports OO programming "better" than Lisp (again, better may just mean different to some). Both languages support OO, functional, procedural, yadda yadda.
RHSeeger
+3  A: 

Most answers on StackOverflow are short, concise answers, and the functional aspects of python make writing that kind of answers easy.

Python's OO-features simply aren't needed in 10-20 line answers, so you don't see them around here as much.

tstenner
exactly, when I start writing I usually prototype functional and when it gets too big too handle I start putting everything neatly in to classes.
thepandaatemyface
+4  A: 

I am both a die-hard OOP and functional programmer and these styles work very well together, mostly because they are completely orthogonal. There are plenty of object-oriented, functional languages and Python is one of them.

So basically, decomposing a application into classes is very helpful when designing a system. When you're doing the actual implementation, FP helps to write correct code.

Also I find it very offensive that you imply that functional programming just means "use folds everywhere". That is probably the biggest and worst misconception about FP. Much has been written of that topic, so I'll just say that the great thing about FP is the idea to combine simple (,correct and reusable) functions into new, more and more complex function. That way it's pretty hard to write "almost correct" code - either the whole thing does exactly what you want, or it breaks completely.

FP in Python mostly revolves around writing generators and their relatives (list comprehensions) and the things in the itertools module. Explicit map/filter/reduce calls are just unneeded.

THC4k
+10  A: 

I mostly use Python using object-oriented and procedural styles. Python is actually not particularly well-suited to functional programming.

A lot of people think they are writing functional Python code by using lots of lambda, map, filter, and reduce, but this is a bit over-simplified. The hallmark feature of functional programming is a lack of state or side effects. Important elements of a functional style are pure functions, recursive algorithms, and first class functions.

Here are my thoughts on functional programming and Python:

  • Pure functions are great. I do my best to make my module-level functions pure.

    • Pure functions can be tested. Since they do not depend on outside state, they are much easier to test.
    • Pure functions are able to support other optimizations, such as memoization and trivial parallelization.
  • Class-based programming can be pure. If you want an equivalent to pure functions using Python classes (which is sometimes but not always what you want),

    • Make your instances immutable. In particular, this mainly means to make your methods always return new instances of your class rather than changing the current one.
    • Use dependency injection rather than getting stuff (like imported module) from global scope.
    • This might not always be exactly what you want.
  • Don't try to avoid state all together. This isn't a reasonable strategy in Python. For example, use some_list.append(foo) rather than new_list = some_list + [foo], the former of which is more idiomatic and efficient. (Indeed, a ton of the "functional" solutions I see people use in Python are algorithmically suboptimal compared to just-as-simple or simpler solutions that are not functional or are just as functional but don't use the functional-looking tools.)

  • Learn the best lessons from functional programming, for example mutable state is dangerous. Ask yourself, Do I really want to change this X or do I want a new X?

    • One really common place this comes up is when processing a list. I would use

      foo = [bar(item.baz()) for item in foo]
      

      rather than

      for index, _ in enumerate(foo):
          foo[index] = bar(foo[index].baz())
      

      and stuff like it. This avoids confusing bugs where the same list object is stored elsewhere and shouldn't be changed. (If it should be changed, then there is a decent chance you have a design error. Mutating some list you have referenced multiple places isn't a great way to share state.)

  • Don't use map and friends gratuitously. There is nothing more functional about doing this.

    • map/filter are not more functional than list comprehensions. List comprehensions were borrowed from Haskell, a pure functional language. map and especially filter can be harder to understand than a list comprehension. I would never use map or filter with a lambda but might if I had a function that already existed; I use map a decent bit.
    • The same goes for itertools.imap/ifilter compared to generator expressions. (These things are somewhat lazy, which is something great we can borrow from the functional world.)
    • Don't use map and filter for side effects. I see this with map a lot, which both makes hard-to-understand code, unneeded lists, and is decidedly not functional (despite people thinking it must be because of map.) Just use a for loop.
    • reduce is confusing except for very simple cases. Python has for loops and there is no hurt in using them.
  • Don't use recursive algorithms. This is one part of functional programming Python just does not support well. CPython (and I think all other Pythons) do not support tail call optimization. Use iteration instead.

  • Only use lambda when you are defining functions on the fly. Anonymous functions aren't better than named functions, the latter of which are often more robust, maintainable, and documented.

Mike Graham