Являются ли представления Python списками того же самого, что и map/grep в Perl?
У меня возникли проблемы с поиском синтаксиса понимания списков в Python, поэтому я начал думать о том, как добиться того же самого в Perl, с которым я больше знаком. Я понял, что основные примеры (взятые из на этой странице) могут быть выполнены в Perl с помощью map
или grep
.
например.
(python) (perl)
S = [x**2 for x in range(10)] @S = map { $_**2 } ( 0..9 );
V = [2**i for i in range(13)] @V = map { 2**$_ } ( 0..12 );
M = [x for x in S if x % 2 == 0] @M = grep { $_ % 2 == 0 } @S;
Итак, это "понимание списка" просто причудливый термин для "карты и/или фильтрации списка" или есть ли еще что-то?
Ответы
Ответ 1
Вы правы: понимание списка - это просто синтаксический сахар для карты и фильтра (термины из мира функционального программирования).
Надеемся, что этот примерный код демонстрирует их равенство:
>>> # 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, вам придется обернуть вызовы для сопоставления или фильтрации в конструкторе list
, потому что карта и фильтр были обновлены, чтобы возвращать итераторы, а не списки.
>>> # 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
Ответ 2
Да, они в основном одинаковы.
Фактически Python также имеет функцию отображения:
S = map(lambda x: x**2, range(10))
совпадает с вашими предыдущими примерами. Однако синтаксис понимания списков настоятельно рекомендуется в Python. Я считаю, что Гвидо был процитирован, говоря, что он сожалеет о представлении функционального синтаксиса вообще.
Однако, когда он становится действительно интересным, в следующей эволюции понимается список, который является генератором. Они позволяют вам возвращать итератор, а не обрабатывать весь список сразу, он выполняет одну итерацию и затем возвращает, так что вам не нужно одновременно удерживать весь список в памяти. Очень мощный.
Ответ 3
Они представляют собой "pythonic" версию для сопоставления и фильтрации последовательностей, но они позволяют делать некоторые другие вещи, например, сглаживать вложенный список (фиксированный уровень), например:
[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]
Ответ 4
Смысл списка также сглаживает вещи:
Например:
[(x, y) для x в xrange (10), если x% 2 == 0 для y в xrange (20), если x!= y]
Если вы использовали вложенные карты здесь, вам также придется использовать concat (суммирование списков).
Ответ 5
Пояснения списков более мощные, чем карта или фильтр, поскольку они позволяют вам абстрактно воспроизводить списки.
Также удобнее использовать их, когда ваши карты еще больше вложены с большим количеством карт и фильтров.
Ответ 6
Да. Синтаксис синтаксиса Python заключается в том, что один и тот же синтаксис (в круглых, а не квадратных скобках) также используется для определения генераторов, которые производят последовательности значений по запросу.