python 类型提示无或某事

问题描述 投票:0回答:3

考虑以下片段

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

re.match
的类型为
Match
或 None。

res = uri_match.group(1)

这行表示

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

python mypy python-typing
3个回答
1
投票

静态类型检查器告诉您,如果您的

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

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


1
投票

您可以通过

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


0
投票

告诉 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
方法干净得多,而且犯错误的机会也更少(特别是在尝试/例外的情况下)

© www.soinside.com 2019 - 2024. All rights reserved.