I'm coming to Python from Clojure, and was wondering if there is a way to have a "temporary variable" inside a generator.
In Clojure, I can use a let
inside a for generator to name an intermediary computation on the item:
(def fnames ["abc1234" "abcdef" "1024"])
(for [fname fnames
:let [matches (re-matches #"(\w+?)(\d+)" fname)]
:when matches]
matches)
;=> (["abc10" "abc" "1234"] ["1024" "1" "024"])
In Python, I need to use a generator twice to filter out the None
results:
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')]
So, is there a way to do something like the following? If not, what is the most Pythonic way?
matches = [re.match('(\w+?)(\d+)', fname) as match
for fname in fnames
if match is not None]
No, there is no direct equivalent of Clojure's let
. The basic structure of Python's list comprehension is:
[name for name in iterable if condition]
where the if condition
part is optional. That is all that the grammar provides for.
In your specific case though, you could put a generator expression inside the list comprehension:
matches = [m.groups() for m in (re.match('(\w+?)(\d+)', f) for f in fnames) if m]
Demo:
>>> 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')]
>>>
Also, you will notice that I removed the is not None
part of your condition. While it is generally a good idea to explicitly test for None
, it is not needed in this case since re.match
always returns either a match object (a truthy value) or None
(a falsey value).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.