Python 列表推导中的 lisp 风格 `let` 语法

6 投票
5 回答
2814 浏览
提问于 2025-04-15 17:04

考虑以下代码:

>>> colprint([
        (name, versions[name][0].summary or '')
        for name in sorted(versions.keys())
    ])

这段代码的作用是按照字典 versions 中的 keys 的升序来打印元素,但由于 value 是另一个已排序的列表,所以只打印它的第一个元素(也就是最大值)的摘要。

因为我对 lisp 中的 let 很熟悉,所以我把上面的代码改写成了:

>>> colprint([
        (name, package.summary or '')
        for name in sorted(versions.keys())
        for package in [versions[name][0]]
    )]

你觉得这样做是否违反了 Pythonic 的原则? 有什么可以改进的地方吗?

注意:对于好奇的人,colprint 的定义可以在 这里找到。

5 个回答

4

所以你在用“for x in [y]”来代替“let x y”。

在一种语言中模仿另一种语言的写法通常不是个好主意。我觉得原来的写法要清晰得多。

5

我在大多数情况下不会使用“复杂的for循环”(或者说“let等价”),但如果这样做能自然地避免重复,尤其是避免那些耗费资源的重复,我就会用。例如:

xs = [(y, y*1.2, y-3.4) for z in zs for y in [somefun(z)] ]

这样看起来比调用somefun三次要好得多!所以,即使在不去除重复的情况下可能不值得使用,但还是值得记住的。

7

为什么不利用元组呢?

colprint([(name, version[0].summary or '')
      for (name, version) in sorted(versions.iteritems())])

或者,甚至可以这样做

colprint(sorted([(name, version[0].summary or '')
             for (name, version) in versions.iteritems()]))

另外,你可以考虑在我的第一个例子中去掉 [],这样你就会得到一个生成器,而不是一个列表(这可能有用也可能没用,因为我猜这会打印整个数组,所以你并不会节省任何计算)。

撰写回答