Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I mostly use Python using object-oriented and procedural styles. Python is actually not particularly well-suited to functional programming.</p> <p>A lot of people think they are writing functional Python code by using lots of <code>lambda</code>, <code>map</code>, <code>filter</code>, and <code>reduce</code>, 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.</p> <p>Here are my thoughts on functional programming and Python:</p> <ul> <li><p><strong>Pure functions are great.</strong> I do my best to make my module-level functions pure.</p> <ul> <li>Pure functions can be tested. Since they do not depend on outside state, they are much easier to test.</li> <li>Pure functions are able to support other optimizations, such as memoization and trivial parallelization.</li> </ul></li> <li><p><strong>Class-based programming can be pure.</strong> If you want an equivalent to pure functions using Python classes (which is sometimes but not always what you want), </p> <ul> <li>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.</li> <li>Use dependency injection rather than getting stuff (like imported module) from global scope.</li> <li>This might not always be exactly what you want.</li> </ul></li> <li><p><strong>Don't try to avoid state all together.</strong> This isn't a reasonable strategy in Python. For example, use <code>some_list.append(foo)</code> rather than <code>new_list = some_list + [foo]</code>, 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.)</p></li> <li><p>Learn the best lessons from functional programming, for example <strong>mutable state is dangerous.</strong> Ask yourself, <em>Do I really want to change this X or do I want a new X?</em></p> <ul> <li><p>One really common place this comes up is when processing a list. I would use</p> <pre><code>foo = [bar(item.baz()) for item in foo] </code></pre> <p>rather than</p> <pre><code>for index, _ in enumerate(foo): foo[index] = bar(foo[index].baz()) </code></pre> <p>and stuff like it. This avoids confusing bugs where the same list object is stored elsewhere and shouldn't be changed. (If it <em>should</em> 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.)</p></li> </ul></li> <li><p><strong>Don't use <code>map</code> and friends gratuitously.</strong> There is nothing more functional about doing this.</p> <ul> <li><code>map</code>/<code>filter</code> are <strong>not</strong> more functional than list comprehensions. List comprehensions were borrowed from Haskell, a pure functional language. <code>map</code> and especially <code>filter</code> can be harder to understand than a list comprehension. I would never use <code>map</code> or <code>filter</code> with a lambda but might if I had a function that already existed; I use <code>map</code> a decent bit.</li> <li>The same goes for <code>itertools.imap</code>/<code>ifilter</code> compared to generator expressions. (These things are somewhat lazy, which is something great we can borrow from the functional world.)</li> <li>Don't use <code>map</code> and <code>filter</code> for side effects. I see this with <code>map</code> a lot, which both makes hard-to-understand code, unneeded lists, and is decidedly not functional (despite people thinking it must be because of <code>map</code>.) Just use a for loop.</li> <li><code>reduce</code> is confusing except for very simple cases. Python has for loops and there is no hurt in using them.</li> </ul></li> <li><p><strong>Don't use recursive algorithms.</strong> 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. <strong>Use iteration instead.</strong></p></li> <li><p><strong>Only use <code>lambda</code> when you are defining functions on the fly.</strong> Anonymous functions aren't better than named functions, the latter of which are often more robust, maintainable, and documented.</p></li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload