第import re; print(re.findall("(.*) (.*)", "john smith"))
行输出[("john", "smith")]
,可以像[(first_name, last_name)] = re.findall(...)
一样解压缩。但是,如果不匹配(findall
返回[]
),则此拆包将引发ValueError: not enough values to unpack (expected 1, got 0)
。
安全地 解包此元组数组的正确方法是什么,这将在匹配([("john", "smith")]
)和不匹配([]
)场景中工作? / p>
答案 0 :(得分:1)
一般的答案是在飞跃之前先看一下
if result:
[(first_name, last_name)] = result
或请求宽恕:
try:
[(first_name, last_name)] = result
except ValueError:
pass
,但是实际上您通过使用re.findall()
查找单个结果来使事情复杂化。使用re.seach()
并提取您的matched groups:
match = re.search("(.*) (.*)", value)
if match:
firstname, lastname = match.groups()
或
try:
firstname, lastname = re.search("(.*) (.*)", value).groups()
except AttributeError:
# An attribute error is raised when `re.search()` returned None
pass
答案 1 :(得分:0)
没有一个;您必须明确检查返回值,以查看是否确实有需要解压缩的内容。
x = re.findall(...)
if x:
[(first_name, last_name)] = x
在Python 3.8中,您可以对此进行稍微压缩:
if x := re.findall(...):
[(first_name, last_name)] = x
答案 2 :(得分:0)
由于re.findall
在不匹配的情况下返回空列表,因此您可以使用or
运算符为first_name
和last_name
分配默认值:
[(first_name, last_name)] = re.findall("(.*) (.*)", "johnsmith") or [(None, None)]
答案 3 :(得分:0)
这很糟糕,所以不要这样做,但是您可以使用
first, last = getattr(re.search(r"(.*) (.*)", "john smith"), 'groups', lambda: (None, None))()
在不使用findall
的情况下做单线工作(这可能返回多个匹配,因此仍然失败,或者忽略空格,具体取决于是否将.
限制为{{1 }}。
鉴于您的模式电流实际上匹配其中具有单个空格的所有内容(捕获最终空格之前的所有内容,以及捕获其之后的所有内容),请避免使用\S
并不会带来太多好处,但是如果您想实际排除内容多于一个空间或仅部分匹配的内容,您可以将findall
切换为.
,甚至可以将\S
切换为search
:
fullmatch
无论哪种方式,它都滥用不匹配返回first, last = getattr(re.fullmatch(r"(\S*) (\S*)", "john smith"), 'groups', lambda: (None, None))()
的事实,而None
没有groups
方法,因此getattr
可以在对象上返回绑定的groups
方法匹配,否则返回lambda
的默认值。无论如何,您都立即调用它,并获得groups
或lambda
的结果。
再次,不要这样做。这是合法的,只是丑陋(而且可能比任何合理的方法都要慢)。