Python 列表推导中的 lisp 风格 `let` 语法
考虑以下代码:
>>> 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()]))
另外,你可以考虑在我的第一个例子中去掉 []
,这样你就会得到一个生成器,而不是一个列表(这可能有用也可能没用,因为我猜这会打印整个数组,所以你并不会节省任何计算)。