简体   繁体   English

Python列表理解与Perl中的map / grep是一回事吗?

[英]Are Python list comprehensions the same thing as map/grep in Perl?

I was having some trouble grokking the list comprehension syntax in Python, so I started thinking about how to achieve the same thing in Perl, which I'm more familiar with. 我在使用Python中的列表理解语法时遇到了一些麻烦,所以我开始考虑如何在Perl中实现相同的功能,我更熟悉它。 I realized that the basic examples (taken from this page ) can all be done in Perl with map or grep . 我意识到基本的例子(取自本页 )都可以在Perl中用mapgrep

Eg 例如

(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;

So is "list comprehension" just a fancy term for "map and/or filter a list" or is there more to it? 那么“列表理解”只是“地图和/或过滤列表”的一个奇特术语,还是更多呢?

You are correct: a list comprehension is essentially just syntactic sugar for map and filter (terms from the functional programming world). 你是对的:列表推导基本上只是地图和过滤器的语法糖(来自函数式编程世界的术语)。

Hopefully this sample code demonstrates their equality: 希望此示例代码演示它们的相等性:

>>> # 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

Note that this is only valid in Python 2.X, as SilentGhost pointed out in the comment. 请注意,这仅在Python 2.X中有效,正如SilentGhost在注释中指出的那样。 To make this compatible with Python 3, you'll have to wrap the calls to map or filter in the list constructor, because map and filter have been updated to return iterators, not lists. 为了使其与Python 3兼容,您必须在list构造函数中包含对map或filter的调用,因为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

Yes, they are basically the same. 是的,它们基本相同。

In fact Python also has a map function: 实际上Python也有一个map函数:

S = map(lambda x: x**2, range(10))

is the same as your first examples above. 与上面的第一个例子相同。 However, the list comprehension syntax is strongly preferred in Python. 但是,列表推导语法在Python中是首选。 I believe Guido has been quoted as saying he regrets introducing the functional syntax at all. 我相信Guido被引用说他遗憾地介绍了功能语法。

However, where it gets really interesting is in the next evolution of list comprehensions, which is generators. 然而,它真正有趣的地方在于列表推导的下一个演变,即生成器。 These allow you to return an iterator - rather than processing the whole list at once, it does a single iteration and then returns, so that you don't have to hold the whole list in memory at the same time. 这些允许您返回迭代器 - 而不是一次处理整个列表,它只进行一次迭代然后返回,这样您就不必同时将整个列表保存在内存中。 Very powerful. 很强大。

They're the "pythonic" version for mapping and filtering sequences, but they allow to do some others things, like flattening a (fixed level) nested list, for example: 它们是用于映射和过滤序列的“pythonic”版本,但它们允许执行其他一些操作,例如展平(固定级别)嵌套列表,例如:

[j for i in nested_list for j in i]

Another thing that you cannot do with a regular map and a lambda expression is to structurally decompose the iterating values, for example: 使用常规映射和lambda表达式无法做的另一件事是在结构上分解迭代值,例如:

[(x%y)*z for x,y,z in list_with_triplets_of_ints]

of course there are workarounds like: 当然有一些解决方法,如:

aux = lambda x,y,z: (x%y)*z
map(lambda t: aux(*t), list_with_triplets_of_ints)

but when the transformation you need to apply is already defined, then usually it's just simpler to use a map, like in: 但是当你需要应用的转换已经定义时,通常使用地图会更简单,例如:

map(int, list_of_str_values)

rather than 而不是

[int(i) for i in list_of_str_values]

List comprehensions also flatten out things: 列表理解也使事情变得平淡:

For example: 例如:

[(x, y) for x in xrange(10) if x%2 == 0 for y in xrange(20) if x!=y] [(x,y)x中x(10)如果x%2 == 0表示x中的y(20)如果x!= y]

If you used nested maps here, you'd have to use concat (summing the lists) too. 如果你在这里使用嵌套映射,你也必须使用concat(汇总列表)。

List comprehensions are more powerful than map or filter as they allow you to abstractly play with lists. 列表推导比映射或过滤更强大,因为它们允许您抽象地使用列表。

It also more convenient to use them when your maps are further nested with more maps and filter calls. 当您的地图进一步嵌套更多地图和过滤器调用时,使用它们也更方便。

Yes. 是。 The power of the Python syntax is that the same syntax (within round rather than square brackets) is also used to define generators, which produce sequences of values on demand. Python语法的强大之处在于,相同的语法(在圆形而不是方括号内)也用于定义生成器,生成器按需生成值序列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM