Live data from Hacker News

Functional programming with Python

ua.pycon.org

31–40 of 51 posts

Re: Functional programming with Python

#32
post #27

It seems to me if you want to write code like this, you shouldn't write it in Python. Python has much simpler, built-in ways to do most of the things he's suggesting. For instance, he says "good" for this code: reduce(operator.add, map(len, ss)) No! The simpler (and more efficient, as it doesn't have to build a list of results!) way to do that is using the built-in sum() with a generator expression: sum(len(s) for s…

> ...faster and often clearer than lambdas.

    $ python -m timeit 'import string;from operator import itemgetter;[itemgetter('slice') for x in string.letters]'
    100000 loops, best of 3: 14.2 usec per loop
    $ python -m timeit 'import string;from operator import itemgetter;[lambda x: x.slice for x in string.letters]'
    100000 loops, best of 3: 10.4 usec per loop
> Also: namedtuple is great instead of "using classes as attribute containers".

Er, OK. Just don't look at the implementation[1]. Cannot be unseen.

[1]: http://hg.python.org/cpython/file/2.7/Lib/collections.py#l23...

Re: Functional programming with Python

#33
post #32
post #27

It seems to me if you want to write code like this, you shouldn't write it in Python. Python has much simpler, built-in ways to do most of the things he's suggesting. For instance, he says "good" for this code: reduce(operator.add, map(len, ss)) No! The simpler (and more efficient, as it doesn't have to build a list of results!) way to do that is using the built-in sum() with a generator expression: sum(len(s) for s…

> ...faster and often clearer than lambdas. $ python -m timeit 'import string;from operator import itemgetter;[itemgetter('slice') for x in string.letters]' 100000 loops, best of 3: 14.2 usec per loop $ python -m timeit 'import string;from operator import itemgetter;[lambda x: x.slice for x in string.letters]' 100000 loops, best of 3: 10.4 usec per loop > Also: namedtuple is great instead of "using classes as attribu…

My eyes... So a named tuple is just a class, nothing special about it really

Re: Functional programming with Python

#34
post #32
post #27

It seems to me if you want to write code like this, you shouldn't write it in Python. Python has much simpler, built-in ways to do most of the things he's suggesting. For instance, he says "good" for this code: reduce(operator.add, map(len, ss)) No! The simpler (and more efficient, as it doesn't have to build a list of results!) way to do that is using the built-in sum() with a generator expression: sum(len(s) for s…

> ...faster and often clearer than lambdas. $ python -m timeit 'import string;from operator import itemgetter;[itemgetter('slice') for x in string.letters]' 100000 loops, best of 3: 14.2 usec per loop $ python -m timeit 'import string;from operator import itemgetter;[lambda x: x.slice for x in string.letters]' 100000 loops, best of 3: 10.4 usec per loop > Also: namedtuple is great instead of "using classes as attribu…

You're measuring the wrong thing. itemgetter() is supposed to be called just once and it's the returned function that is used in the loop/map. It should be:

    python -m timeit 'import string;from operator import itemgetter; getter=itemgetter('slice'); [getter(x) for x in string.letters]'

Re: Functional programming with Python

#35
post #18

Note that `reduce` has been, if not deprecated, then at least discouraged (not that I agree with this, but reduce gets taken away in Python 3, so it's probably good form to stop using it). The author does `reduce(operators.add, lst)` a lot; you can do that using `sum(lst)` instead.

reduce() is just moved to a library instead of being a builtin, it's not really a big deal. And of course sum() is better, addition is just the typical example for exposition (he later notes that shorter forms are always better). Whether it's good form to stop using it only depends on whether you prefer more explicit for-loops.

Re: Functional programming with Python

#36
post #10
post #5

I'm curious, on the Currying (Standard Library) slide, the author uses `attrgetter` from the `operator` module -- I've always used `getattr` to achieve the same thing. Am I missing something by not using `attrgetter`?

Short answer: not really. Long answer: In [1]: from operator import attrgetter In [2]: class Person: ...: def __init__(self, name): ...: self.name = name ...: In [3]: me = Person('walrus') In [4]: getattr(me, 'name') Out[4]: 'walrus' In [5]: attrgetter('name')(me) Out[5]: 'walrus' This is potentially useful if you're using `map`: In [6]: people = [me, Person('aschwo')] In [7]: list(map(lambda obj: getattr(obj, 'name'…

On the last point, a list comprehension is just a much a functional programming idiom--Python got them from Haskell! I use both in my code, whichever is shortest.

PS: map returns a list, no need to call list() on it.

Re: Functional programming with Python

#37

Earlier quoted context omitted.

I was writing a really long response to your post, explaining how reduce/inject/fold is abstracting out an absurdly common iteration pattern, and using it can expose structural similarities between many superficially different computations, and how (unlike map and filter) it can't be expressed as a list comprehension, so removing it was super lame. But in the process of translating a comment I wrote in another forum…

If __add__ is taken to be any associative operation of a monoid, then Python's sum is merely equivalent to Haskell's mconcat, which is not nearly as general as reduce/foldl. Plus, unless you implement something akin to newtype wrappers for alternative monoid instances (hardly Pythonic), you're going to be restricted to a single foldable function for any given type. I think you were right the first time; removing redu…

Don't worry, it has not been removed: http://docs.python.org/3/library/functools.html?highlight=re...

Re: Functional programming with Python

#38

I'm not sure I agree with "don't write classes". This is Python: classes are the state container. That's the structure Python provides for grouping related pieces of information together, and that's the structure all other Python libraries and programmers expect you to use. Now if you don't want to type the code every time, that's fine: use collections.namedtuple.

A class without methods is just syntactic sugar wrapping around a dictionary of attributes, so in that sense it could be simpler to use the dictionary directly.

Re: Functional programming with Python

#39
post #29
post #4

Forgot one big con: Python lambda functions aren't "proper" functions (ie. arbitrary multi-line code blocks). Guido van Rossum has addressed this many times, saying (in effect) "it adds undue complexity and would be un-Pythonic", eg: http://www.artima.com/weblogs/viewpost.jsp?thread=147358 This is one of my (very few!) gripes with FP in Python.

I fail to see how this makes them non-proper functions, a better way to put it is they are a subset of possible functions.

Yes, single-expression functions are a subset of all possible functions... but that's not exactly what I was getting at. I put "proper" in quotes just to signify that they have subtle differences that, from a purely type-based abstraction, are different from named functions. For example, you can't serialize (pickle) a lambda function.

Re: Functional programming with Python

#40

Earlier quoted context omitted.

I was writing a really long response to your post, explaining how reduce/inject/fold is abstracting out an absurdly common iteration pattern, and using it can expose structural similarities between many superficially different computations, and how (unlike map and filter) it can't be expressed as a list comprehension, so removing it was super lame. But in the process of translating a comment I wrote in another forum…

If __add__ is taken to be any associative operation of a monoid, then Python's sum is merely equivalent to Haskell's mconcat, which is not nearly as general as reduce/foldl. Plus, unless you implement something akin to newtype wrappers for alternative monoid instances (hardly Pythonic), you're going to be restricted to a single foldable function for any given type. I think you were right the first time; removing redu…

> If __add__ is taken to be any associative operation of a monoid, then Python's sum is merely equivalent to Haskell's mconcat, which is not nearly as general as reduce/foldl

I don't have the math to back this up, so please correct me if you know otherwise (and especially if you can demonstrate otherwise, though I know this being wrong is not contingent on that), but: I'm pretty sure `mconcat` with a `map` (or a list comprehension) is exactly as general as `fold`.

> Plus, unless you implement something akin to newtype wrappers for alternative monoid instances (hardly Pythonic), you're going to be restricted to a single foldable function for any given type.

Again, I know this isn't an argument and demonstrates shitty memory on my part, but a single solid example here would be key to me understanding this debate:

What is an example of a type with more than 2 monoids on it, whose fold could not be cleanly expressed with a sum/product and a map/comprehension, which is not already included in the standard library (any/all/gcd/lcm/max/min)?

[I suspect there either won't be an easy answer, or it will be so basic that I'll be brutally embarrassed... this is all kinda talking out of my ass, I have no exposure to category theory outside of reading haskell papers]

Post reply on HN