提问人:Joe J 提问时间:10/27/2023 最后编辑:Joe J 更新时间:10/27/2023 访问量:50
Python:键入注释函数返回值,该值返回该函数中定义的类
Python: type annotate a function return value that returns a class defined in that function
问:
我想知道对函数或方法的返回值进行类型注释的正确方法是什么,其中类是在该函数中定义的。
例如:
from typing import List
from dataclasses import dataclass
def get_users() -> List['ReturnUser']:
@dataclass
class ReturnUser:
first_name: str
last_name: str
return [
ReturnUser("John", "Doe"),
ReturnUser("Jane", "Doe")]
...ReturnUser 数据类仅在函数范围内相关。(我不关心函数之外的对象,除了我可以在调用代码中访问它的属性)。get_users()
但是,Pylance 将返回值注释显示为类型错误。不幸的是,我的环境是 Python 3.7,但也很好奇较新的 Python 版本中是否存在更新的方法?List['ReturnUser']
如何注释尚不存在的返回值?
答:
3赞
Silvio Mayolo
10/27/2023
#1
不仅还不存在,而且每次都是不同的类。我们可以很容易地验证这一点。ReturnUser
>>> a = get_users()
>>> b = get_users()
>>> type(a[0]) is type(b[0])
False
所以我的第一个建议是不要这样做。创建一个模块级类,并在其前加上下划线,以指示它是私有的。在 Python 中定义 a 内部的充分理由非常非常少。class
def
话虽如此,让我们假设这确实是唯一的方法。假设这里没有显示一些设计约束,并且您无法摆脱该类模式。正如我所说,它不是正确的返回类型,因为该函数每次都返回不同(不相关)类的值。如果您希望函数的返回类型是“带有 and 字段的东西”,我们可以使用 Protocol
来做到这一点。ReturnUser
first_name
last_name
class _ReturnUserLike(Protocol):
first_name: str
last_name: str
def get_users() -> List[_ReturnUserLike]:
# ... Same class body, including the local class ...
现在,对调用方的唯一类型级保证是您具有属性,并且这些属性是字符串。A 是一种结构类型,这意味着出于类型检查的目的,任何看起来像该类的东西都算作实例。first_name
last_name
Protocol
评论
0赞
Joe J
10/27/2023
感谢您对此的回复和建议。我对数据类返回值的想法是,它将是返回数据的短期“持有者”,并且比在元组或字典中返回该数据更具表现力和更好的记录。但是,我认为您将其定义为全局对象的意思,否则它会混淆相等的定义,并且可能只会让该函数的调用者感到困惑(因为他们不知道该对象是什么)。也感谢使用 Protocol 的示例;我也会读到这一点。
0赞
Silvio Mayolo
10/27/2023
不客气!有了补充的信息,我同意尼古拉的观点;我以前遇到过这种情况,这是一个很好的中间地带:它有用于组织和调试目的的命名字段,但可以在调用站点进行解构,就像元组一样。NamedTuple
评论