【问题标题】:Comprehensions in Python and Javascript are only very basic?对 Python 和 Javascript 的理解只是非常基础的?
【发布时间】:2009-10-09 13:39:13
【问题描述】:

查看 Python 和 Javascript 中的推导式,到目前为止,我看不到一些我认为在 Haskell 等语言推导式中最强大的主要功能。

他们是否允许多个生成器之类的东西?还是它们只是一个基本的地图过滤器形式?

如果他们不允许多个生成器,我觉得他们很失望 - 为什么这些东西被遗漏了?

【问题讨论】:

    标签: javascript python haskell list-comprehension


    【解决方案1】:

    Python 允许多个生成器:

    >>> [(x,y,x*y) for x in range(1,5) for y in range(1,5)]
    [(1, 1, 1), (1, 2, 2), (1, 3, 3), (1, 4, 4), 
     (2, 1, 2), (2, 2, 4), (2, 3, 6), (2, 4, 8), 
     (3, 1, 3), (3, 2, 6), (3, 3, 9), (3, 4, 12),
     (4, 1, 4), (4, 2, 8), (4, 3, 12), (4, 4, 16)]
    

    还有限制:

    >>> [(x,y,x*y) for x in range(1,5) for y in range(1,5) if x*y > 8]
    [(3, 3, 9), (3, 4, 12), (4, 3, 12), (4, 4, 16)]
    

    更新:Javascript的语法类似(在firefox上使用javascript shell的结果):

    var nums = [1, 2, 3, 21, 22, 30];
    var s = eval('[[i,j] for each (i in nums) for each (j in [3,4]) if (i%2 == 0)]');
    s.toSource();
    [[2, 3], [2, 4], [22, 3], [22, 4], [30, 3], [30, 4]]
    

    (出于某种原因,在 javascript shell 中评估有关上下文内容的某些内容需要 eval 间接以使列表推导起作用。<script> 标记内的 Javascript 当然不需要这样做)

    【讨论】:

    • 酷。现在所有 Python 需要的是生成器中的模式匹配。并将超越序列的理解推广到其他单子。呃 - 一个打字机检查器。 :)
    • 没有。 Python 不是 Haskell。类型检查违背了 python 的哲学。
    • 静态类型检查最终被拒绝这一事实足以表明它不是pythonic。关于 Python 的要点之一是活力——而不仅仅是 wrt/打字。请记住,在 Python 中,您可以在运行时添加/替换/删除属性和方法,无论是基于每个对象还是每个实例。您甚至可以在运行时 FWIW 更改对象的类。更糟糕的是 - 'class' 是一个运行时可执行语句。祝你好运,静态类型检查!-)
    • 通过避免在静态类型语言中进行类型检查,您经常会遇到问题,因为编译器假定类型检查存在并且有用。在 C 语言中,您通常以指针结尾,然后您使用错误的指针和 kablam 做错事。如果您愿意,在 Python 中检查类型是微不足道的。 assert isinstance(ob, type)
    • @Rowan 静态类型是一种优化,不需要学习如何编程。学习编程 SICP 使用方案的最佳书籍之一。
    【解决方案2】:

    是的,Python list comprehension 中可以有多个迭代:

    >>> [(x,y) for x in range(2) for y in range(3)]
    [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]
    

    【讨论】:

    • 酷,我很高兴。我只是想知道为什么我不能轻易找到这些信息......维基百科或其他地方的例子似乎都没有包含这个。现在我不喜欢的是与 Haskell 相比的语法。 :) Javascript 呢?
    【解决方案3】:

    同时添加一个 if 语句...

    >>> [(x,y) for x in range(5) for y in range(6) if x % 3 == 0 and y % 2 == 0]
    [(0, 0), (0, 2), (0, 4), (3, 0), (3, 2), (3, 4)]
    

    【讨论】:

      【解决方案4】:

      Haskell 中的 Comprehensions 在很大程度上是非常强大的,因为 Haskell 是函数式的,所以对它们来说非常有意义。 Python 没有功能,所以它的意义不大。

      您可以在 Python 中使用推导式做很多复杂的事情,但很快就会变得难以阅读,从而违背了整个目的(意味着您应该以其他方式来做)。

      然而,正如这里所指出的,python 确实允许在推导中使用多个生成器。

      【讨论】:

      • 最后我听说,Python 的优势之一是它支持函数式编程,并包含闭包之类的东西。是否有另一种方法可以在 Python 中实现更优雅的多生成器理解?
      • Python 对函数式编程的支持有限——主要是因为 Python 函数是真正的对象。它还从函数式语言中借用了几个结构。但它基本上仍然是一种命令式的面向对象语言。此外,“优雅”的pythonesque 定义是可读性。多生成器推导式通常更易读(至少对大多数程序员而言),写成普通的“for”循环。
      • @Rowan:是的,通常是 for 循环。您还想考虑使用yield__next__ 创建自己的生成器。
      • Python 不能很好地支持函数式编程(当然比 Java 还多),而且它不支持闭包,而是给他们一个简短的、软弱的握手。 Python 中的 Lambda 被归为与 OCaml 中的 for 循环相同的二等公民身份。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-07
      • 1970-01-01
      • 2017-03-30
      • 2016-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多