Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Oh my. functional style is good for functional languages, sure. But in python?

    total = sum([f(record) for record in housing_records])
should be better and more readable than

    x = 0
    for element in data:
        x = x + f(element)
This guy is crazy.


The best one would be:

total = sum(map(f, data))

Not only does it take less resources as it only has to loop once because map creates a generator. This is absolutly the use case of map, if you want to apply the same function, which is already defined, to all members of a list/iterator, map is the correct tool for the job. Now if you wanted to apply a transformation that is not in a function there would be an argument to use a comprehension as it would be better than using an inline lambda in a map. But if you already have the method you want to apply, just use map() and then pass that to sum()


A generator expression would also avoid looping twice - this is valid python:

  total = sum(f(record) for record in housing_records)


Python is expressly designed to be non-functional. Guido van Rossum believed that the paradigm for the language should instead be “pythonic.” [1]

[1] http://neopythonic.blogspot.com/2009/04/tail-recursion-elimi...


This won't keep the list in memory like you do:

    sum(i for i in range(4))


( instead of [ in the list comprehension turns it into a generator, avoiding the problem you describe.


Maybe it's just too early in the morning for me or I don't know enough about Python, but why would the OPs code snippet keep the list in memory, and why is yours an improvement?

Also, is this something you could handwave because of Python's garbage collection, or is that not going to help in this case?


The OP's version is creating the list, then processing it.

The second version is an generator; it skips the 'creating the list' part.


Ohhhhh. The coffee's kicked in. Thanks for explaining. To recap, a list comprehension:

1. Creates a new, duplicate list containing every record in housing_records

2. Loops through the new list

3. Applies f() to each element and updates the new list as it loops

4. Sum() sums all the elements in the list by accessing each element and adding it to a total

Note: All returned values of f() are stored in memory at the end of step 3. This is a waste.

A generator:

1. Creates a generator object that contains nothing but acts like a list

2. When sum() accesses an element in the generator object, the generator object applies f() to the element in housing_list and returns the value

3. Sum() is therefore able to sum all the elements by "accessing" each element and adding it to a total

Note: Only one result of f() is stored in memory at any given time. Much better.


The top one using list comprehension is easily understood for anyone who did non trivial work in Python. And more concise, no run away variables, etc.

The bottom one is understood also by developers with no Python experience.

So I guess it depends on the audience.


I feel I am the first type of audience, and have no problem understanding both versions(having programmed in multiple functional languages).

But when I see the bottom version I instantly understand what it does, its like I dont need my concious brain involved at all. I can just glance at the "shape" of the code, with my eyes just focusing at a few significant locations (the function call and the +), and I know what it does.

Maybe its because I grew up speaking imperatively. Maybe its that with the imperative version there is extra information in the "shape" of the code which my brain can use. But beeing more concise dont seem to help the second version, I dont read a constant number of characters per second.


Notice the comment "In this codebase", and all the other the other caveats in the good code review. Consistency can be good.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: