воскресенье, 19 октября 2014 г.

Если хочешь быть умён — упражняйся!

Нашел отличный сайтик с упражнениями для программеров.


http://exercism.io/

Предлагает задания, консольного клиента для удобства, и пытается выстроить коммунити вокруг обучения.

Идея, очень хорошая, если вы на работе не программируете парно и с code-review. То очень полезно что б ваш код иногда кто то еще смотрел.

А даже если и программируете со всеми удобствами, всё равно же не на всех языках. Можно попробовать что то новое.


К моему большому сожалению. функциональных языков там нет.

Но, как в анекдоте про хорошо зафиксированного больного, кое что могут и питоны.

Вот так вот выглядит у меня подсчет кол-ва слов в тексте, без циклов и ветвлений.


def word_count(string):
    return [ 
        [None for words_list in [string.split()]], 
        { word: words_list.count(word) for word in set(words_list) } 
    ][-1]
 Жуткий, вырвиглазный код.

Но не вижу другого способа как мне определить локальную переменную сохранившую вызов split внутри генератора.

Посмотрите через python -m cProfile
мой код, на такой вот разнообразной строке
res = [ str(x)+' ' for x in range(1, 10000) ]

показывает

         10006 function calls in 0.874 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.003    0.003    0.874    0.874 wordcount.py:1(<module>)
        1    0.001    0.001    0.871    0.871 wordcount.py:1(word_count)
        1    0.014    0.014    0.870    0.870 wordcount.py:2(<dictcomp>)
     9999    0.856    0.000    0.856    0.000 {method 'count' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
        1    0.001    0.001    0.001    0.001 {method 'split' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {range}

Убираем эту локальную
def word_count(string):
    return 
        { word: string.split().count(word) for word in set(words_list) } 

становится конечно понятнее и красивее, но

20005 function calls in 5.550 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
1 0.003 0.003 5.550 5.550 wordcount.py:1(<module>)
1 0.001 0.001 5.547 5.547 wordcount.py:1(word_count)
1 0.997 0.997 5.545 5.545 wordcount.py:2(<dictcomp>)
9999 0.834 0.000 0.834 0.000 {method 'count' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {method 'join' of 'str' objects}
10000 3.715 0.000 3.715 0.000 {method 'split' of 'str' objects}
1 0.000 0.000 0.000 0.000 {range}

10000 лишних и ненужных вызов split() что убивает всю красоту.