Можно найти некоторый материал об инструментах для веб-приложений Lisp в этот вопрос .
Это могло бы также стоить послушать Подкаст Переполнения стека 27 , где парни Reddit говорят немного об их опыте runnig веб-сайт на Lisp (и их переключатель к Python).
Вы правы: понимание списка - это, по сути, просто синтаксический сахар для карты и фильтра (термины из мира функционального программирования).
Надеюсь, этот пример кода демонстрирует их равенство:
>>> # Python 2
>>> [x**2 for x in range(10)] == map(lambda x: x**2, range(10))
True
>>> [2**i for i in range(13)] == map(lambda x: 2**x, range(13))
True
>>> S = [x**2 for x in range(10)]
>>> [x for x in S if x % 2 == 0] == filter(lambda x: x % 2 == 0, S)
True
Примечание что это действительно только в Python 2.X, как указал SilentGhost в комментарии. Чтобы сделать это совместимым с Python 3, вам придется заключить вызовы map или filter в конструктор list
, поскольку map и filter были обновлены, чтобы возвращать итераторы, а не списки.
>>> # Python 3
>>> [x**2 for x in range(10)] == list(map(lambda x: x**2, range(10)))
True
>>> [2**i for i in range(13)] == list(map(lambda x: 2**x, range(13)))
True
>>> S = [x**2 for x in range(10)]
>>> [x for x in S if x % 2 == 0] == list(filter(lambda x: x % 2 == 0, S))
True
Да, в основном они одинаковы.
На самом деле Python также имеет функцию карты:
S = map(lambda x: x**2, range(10))
такой же, как и в ваших первых примерах выше. Однако в Python настоятельно рекомендуется использовать синтаксис понимания списка. Я считаю, что цитировали Гвидо, сказавшего, что он вообще сожалеет о введении функционального синтаксиса.
Однако действительно интересным становится следующая эволюция понимания списков - генераторы. Это позволяет вам возвращать итератор - вместо того, чтобы обрабатывать весь список сразу, он выполняет одну итерацию, а затем возвращается, так что вам не нужно одновременно удерживать весь список в памяти. Очень мощный.
Это "питоническая" версия для отображения и фильтрация последовательностей, но они позволяют делать некоторые другие вещи, такие как сглаживание вложенного списка (фиксированного уровня), например:
[j for i in nested_list for j in i]
Еще одна вещь, которую вы не можете сделать с обычной картой и лямбда-выражением, это для структурной декомпозиции повторяющихся значений, например:
[(x%y)*z for x,y,z in list_with_triplets_of_ints]
Конечно, есть обходные пути вроде:
aux = lambda x,y,z: (x%y)*z
map(lambda t: aux(*t), list_with_triplets_of_ints)
, но когда преобразование, которое вам нужно применить, уже определено, тогда обычно проще использовать карту, например:
map(int, list_of_str_values)
, а не
[int(i) for i in list_of_str_values]
Понимание списков также выравнивает вещи:
Например:
[(x, y) для x в xrange (10) if x% 2 == 0 для y в xrange (20) if x! = Y]
Если бы вы использовали здесь вложенные карты, у вас были бы также использовать concat (суммирование списков).
Да. Сила синтаксиса Python заключается в том, что тот же синтаксис (в круглых, а не квадратных скобках) также используется для определения генераторов, которые по запросу создают последовательности значений.
Понимание списков более мощное средство, чем карта или фильтр, поскольку они позволяют вам абстрактно играть со списками.
Также их удобнее использовать, когда ваши карты дополнительно вложены с большим количеством карт и фильтров звонки.