Python生成器是否有`let`或`as`关键字?

时间:2014-11-18 02:39:02

标签: python syntax clojure generator

我是从Clojure来到Python的,并且想知道是否有办法拥有一个"临时变量"在发电机内。

在Clojure中,我可以在for生成器中使用let来命名项目的中间计算:

(def fnames ["abc1234" "abcdef" "1024"])
(for [fname fnames
      :let [matches (re-matches #"(\w+?)(\d+)" fname)]
      :when matches]
  matches)
;=> (["abc10" "abc" "1234"] ["1024" "1" "024"])

在Python中,我需要使用两次生成器来过滤掉None结果:

fnames = ["abc1234", "abcdef", "1024"]
matches = [re.match('(\w+?)(\d+)', fname) for fname in fnames]
matches = [match.groups() for match in matches if match is not None]
# [('abc', '1234'), ('1', '024')]

那么,有没有办法做以下事情?如果没有,那么最恐怖的方式是什么?

matches = [re.match('(\w+?)(\d+)', fname) as match 
   for fname in fnames
   if match is not None]

1 个答案:

答案 0 :(得分:5)

不,没有直接相当于Clojure的let。 Python列表理解的基本结构是:

[name for name in iterable if condition]

if condition部分是可选的。这就是grammar提供的所有内容。


在您的具体情况下,您可以在列表理解中添加generator expression

matches = [m.groups() for m in (re.match('(\w+?)(\d+)', f) for f in fnames) if m]

演示:

>>> import re
>>> fnames = ["abc1234", "abcdef", "1024"]
>>> matches = [m.groups() for m in (re.match('(\w+?)(\d+)', f) for f in fnames) if m]
>>> matches
[('abc', '1234'), ('1', '024')]
>>>

另外,您会注意到我删除了is not None部分条件。虽然明确测试None通常是个好主意,但在这种情况下不需要它,因为re.match总是返回匹配对象(真值)或None(假的)值)。