考虑以下片段
uri_match: Optional[Match[str]] = re.match(r"https//(.+?)/(.+)", "bla bla")
re.match
的类型为 Match
或 None。
res = uri_match.group(1)
这行表示
None
没有成员 group
。这意味着类型检查器发现返回可能是 None
并因此引发错误。
我们该如何处理这些?
静态类型检查器告诉您,如果您的
re.match
调用未能找到模式(因此 uri_match
是 None
),第二次调用也会失败,但缺少方法除外。
如何解决这个问题取决于程序的正确行为是什么。也许您可以将一些后备值分配给
uri_match
(或res
),或者您可以获取不同的 "bla blah"
字符串并再次尝试匹配它。
或者失败的匹配可能会使其余代码变得毫无意义,并且任何回退都需要在程序逻辑的更高级别上发生。在这种情况下,引发异常可能是正确的做法(尽管返回像
None
这样的特殊值可能是一种可能的选择)。
这里有一些示例代码,在放弃之前会经历一些不同的意外情况:
uri_match: Optional[Match[str]] = re.match(r"https//(.+?)/(.+)", "bla bla")
if uri_match is None:
uri_match = re.match(r"https//(.+?)/(.+)", "foo bar") # try another input
if uri_match is not None:
res = uri_match.group(1) # condition this line, so it only runs when we have a match
elif default is not None:
res = default # maybe there's some default result we can use?
else:
raise ValueError("Invalid input") # if not, raise an exception
... # use res below
您的代码可能不会完成所有这些事情,但其中一两个可能对您的程序有意义。
您可以通过
if
或 try-except
来处理它。如果您害怕在代码库中使用太多 if
或 try-except
,您可以使用函数来获取结果。所有重复的 if
或 try-except
都会被功能覆盖,所以无需担心。
通过
if
代码处理:
import re
def handle_by_if(s):
uri_match = re.match(r"https://(.+?)/(.+)", s)
if uri_match:
return uri_match.group(1)
print(f"handle_by_if: {s} not match anything")
return ""
print(handle_by_if("https://stackoverflow.com/questions"))
print("-"*20)
print(handle_by_if("bla bla"))
结果:
stackoverflow.com
--------------------
handle_by_if: bla bla not match anything
通过
try-except
代码处理:
def handle_by_try_except(s):
uri_match = re.match(r"https://(.+?)/(.+)", s)
try:
return uri_match.group(1)
except AttributeError:
print(f"handle_by_if: {s} not match anything")
return ""
print(handle_by_try_except("https://stackoverflow.com/questions"))
print("-"*20)
print(handle_by_try_except("bla bla"))
结果:
stackoverflow.com
--------------------
handle_by_if: bla bla not match anything
告诉 mypy 某些事情不能
None
的最简单方法是使用 assert x is not None
或简单的 assert x
。
uri_match = re.match(r"https//(.+?)/(.+)", "bla bla")
assert uri_match
res = uri_match.group(1)
它看起来比
try/except
和if/else
方法干净得多,而且犯错误的机会也更少(特别是在尝试/例外的情况下)