python 类型提示无或其他内容

问题描述

考虑以下片段

uri_match: Optional[Match[str]] = re.match(r"https//(.+?)/(.+)","bla bla")

re.match 的类型为 Match 或无。

res = uri_match.group(1)

这一行表示 None 没有成员 group。这意味着类型检查器看到返回值可能是 None 并因此引发错误。 我们如何处理这些?

解决方法

您可以通过iftry-except来处理。如果您害怕在代码库周围使用太多iftry-except,您可以使用函数来获取结果。所有重复的 iftry-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_matchNone),第二个调用也会失败,例如缺少方法的异常。

你如何解决这个问题取决于你的程序的正确行为是什么。也许您有一些可以分配给 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

您的代码可能不会做所有这些事情,但一两个可能对您的程序有意义。