如何使用具有多个返回类型的函数的结果,而不被警告“赋值中的类型不兼容”?

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

这个问题是在 Python 3.12 的上下文中(因此,利用该语言的最新类型提示功能)和当前版本的

mypy
进行静态类型检查。

考虑下面的示例函数,它将返回一个复杂对象或一个

dict
,具体取决于您要求函数执行的操作。 是否有一种语言可以指定“当它可以返回多种类型时,我知道此函数调用将给我哪个返回值”?

def api_request(*args, as_json: bool = False, **kwargs) -> requests.Response | dict:
  response = requests.request(*args, **kwargs)
  if as_json is True:
    return response.json()
  return response

当我去其他地方使用这个函数时,静态类型检查失败(我正在使用

mypy
):

def another_func():
  response = api_request(as_json=True)
  foo = response["foo"]  # error: Value of type "Response | dict[Any, Any]" is not indexable  [index]

这不起作用:

  response: dict = api_request(as_json=True)  # error: Incompatible types in assignment (expression has type "Response | dict[Any, Any]", variable has type "dict[Any, Any]")  [assignment]

确实,但我觉得首先否定了使用类型提示的全部意义,因为它不是“任何类型”。它将返回一个字典

  response: Any = api_request(as_json=True)
  foo = response["foo"]

在线评论

# type: ignore
也有效

  response = api_request(as_json=True)
  foo = response["foo"]  # type: ignore

但是,这感觉像是作弊/降低了类型检查的有用性。

python polymorphism return-value python-typing mypy
1个回答
0
投票

当您有一个可以返回不同类型值的函数(例如有时返回字符串,有时返回数字),并且您希望使用结果而不从代码编辑器或编译器收到警告或错误时,请在此处您可以做一些事情:

  1. 使用联合类型(如果您的语言支持) 想象一下,您正在编写一个程序,其中的函数可能返回字符串或整数。有些语言允许您明确地说:“嘿,这个函数可能返回这种类型或那种类型。”在 Python 或 TypeScript 等语言中,您可以使用称为 Union 的东西:

蟒蛇 复制代码 从输入 import Union

def example() -> Union[str, int]: return "hello" # 或者返回 42 这告诉编辑器/编译器,“期待一个字符串或一个整数,不要惊慌。”

  1. 使用前请检查类型 如果您的语言不支持联合类型或者您只是想格外小心,则可以在使用之前检查结果的类型。这就像问:“这是什么东西?”在用它做某事之前。

蟒蛇 复制代码 结果 = 示例()

if isinstance(结果, str): print("这是一个字符串:", 结果) elif isinstance(结果, int): print("这是一个整数:", 结果) 这样,您就可以确保在正确的上下文中使用结果。

  1. 类型铸造 有时,您知道返回类型是什么,您只需要告诉编译器,“相信我,我知道我在做什么。”这称为类型转换,您可以手动将结果转换为您期望的类型:

蟒蛇 复制代码 结果 = 示例() string_result = str(result) # 如果你确定它应该是一个字符串 请小心这一点,因为如果你错了,可能会导致问题。

  1. 使用任意或对象类型 在某些语言中,您可以使用非常通用的类型(例如 Any(在 Python 中)或 Object(在 Java 中))来存储结果。这就像在说:“我不在乎它是什么类型,只要把它给我就可以了!”

蟒蛇 复制代码 结果:任意 = 示例() 但是,在对其进行特定操作之前,您需要检查或投射它。

  1. 解构 如果函数返回打包在元组或对象中的多个值,您可以将它们直接解包到变量中:

蟒蛇 复制代码 def 示例(): 返回“你好”,42

str_result, int_result = 示例() 这样,每个变量就可以直接获得正确的类型。

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