问题描述
考虑以下片段
uri_match: Optional[Match[str]] = re.match(r"https//(.+?)/(.+)","bla bla")
re.match
的类型为 Match
或无。
res = uri_match.group(1)
这一行表示 None
没有成员 group
。这意味着类型检查器看到返回值可能是 None
并因此引发错误。
我们如何处理这些?
解决方法
您可以通过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
,
静态类型检查器告诉您,如果您的 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
您的代码可能不会做所有这些事情,但一两个可能对您的程序有意义。