代码之家  ›  专栏  ›  技术社区  ›  friedo

python list的理解是否与perl中的map/grep相同?

  •  17
  • friedo  · 技术社区  · 15 年前

    我在用Python搜索列表理解语法时遇到了一些困难,所以我开始考虑如何用Perl实现相同的功能,这是我更熟悉的。我意识到 this page )都可以用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;
    

    那么,“列表理解”是“映射和/或过滤列表”的一个花哨术语,还是有更多的含义呢?

    6 回复  |  直到 15 年前
        1
  •  14
  •   Mark Rushakoff    15 年前

    你是对的:列表理解本质上只是映射和过滤的语法糖(来自函数式编程世界的术语)。

    希望这个示例代码能够证明它们的相等性:

    >>> # 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
  •  3
  •   Daniel Roseman    15 年前

    是的,基本上是一样的。

    实际上,python还有一个map函数:

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

    与上面的第一个示例相同。但是,在Python中,列表理解语法是首选的。我相信guido被引用说他对引入函数语法感到遗憾。

    然而,真正有趣的是列表理解的下一个进化,它是生成器。它们允许您返回一个迭代器——而不是一次处理整个列表,而是执行一次迭代,然后返回,这样您就不必同时将整个列表保存在内存中。非常强大。

        3
  •  2
  •   fortran    15 年前

    它们是用于映射和过滤序列的“pythonic”版本,但它们允许执行其他一些操作,例如扁平(固定级别)嵌套列表:

    [j for i in nested_list for j in i]
    

    还有一件事你不能用普通的 地图 lambda表达式在结构上分解迭代值,例如:

    [(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
  •  2
  •   Peaker    15 年前

    清单的理解也会使事情变得扁平化:

    例如:

    [(x,y)对于x in xrange(10),如果x%2==0,对于y in xrange(20),如果x!= y]

    如果在这里使用嵌套映射,那么也必须使用concat(求和列表)。

        5
  •  0
  •   TheOne    15 年前

    列表理解比映射或过滤更强大,因为它们允许您抽象地使用列表。

    当您的映射被更多的映射和过滤器调用进一步嵌套时,使用它们也更加方便。

        6
  •  0
  •   Nat    15 年前

    对。python语法的强大之处在于,相同的语法(在圆括号内而不是方括号内)也用于定义生成器,后者根据需要生成值序列。