关于python:为包含namedtuple的List键入提示

Type hint for List that contains a namedtuple

我在这里读过,但它是关于名字的提示。

是否可以为包含namedtupleList创建类型提示?

例如:

1
2
3
4
5
6
firefoxprofile = namedtuple("Profile", ["Name","Path","isRelative","Default"])

# Will contain a list of tuples that represent the firefox profiles.
ffprofiles = [] # -- how would I write the type hint?
ffprofiles.append(Profile(Name='Jason', Path='Profiles/er5rtak4.Jason', isRelative='1', Default=None))
ffprofiles.append(Profile(Name='Sarah', Path='Profiles/23mvfqcj.Sarah', isRelative='1', Default=None))

我尝试过:

1
ffprofiles = List[namedtuple("Profile", ["Name","Path","isRelative","Default"])]

但这不起作用,当我试图用该语法更新ffprofiles = []行时,我得到一个异常:

1
TypeError: descriptor 'append' requires a 'list' object but received a 'Profile'


您不必拼写命名的元组,只需引用您的List[]类型中类型的名称:

1
List[firefoxprofile]

在赋值中使用时,请将类型提示放在冒号之后,但在=之前,遵循PEP 526变量注释语法:

1
ffprofiles: List[firefoxprofile] = []

这会将ffprofiles设置为空列表,并告诉任何类型提示检查程序列表的内容必须是firefoxprofile类型的实例。如果要在该列表中提供一些初始配置文件,只需将它们包含在列表文本中,就不需要在后面附加它们。

您将由namedtuple()生成的类分配给名称firefoxprofile,这样剩下的代码就可以用来引用它,而不是使用名称Profile。不过,您可能希望将namedtuple()结果指定给与第一个参数相同的名称,因此Profile = namedtuple('Profile', ...)

但是,您可能还希望使用typing.NamedTuple类来定义类型化的命名tuple;您链接到的文章涵盖了这一点,但这里它适用于您的示例:

1
2
3
4
5
6
7
8
9
10
11
12
from typing import Optional, NamedTuple, List

class FirefoxProfile(NamedTuple):
    name: str
    path: str
    is_relative: bool
    default: Optional[str]

ffprofiles: List[FirefoxProfile] = [
    FirefoxProfile('Jason', 'Profiles/er5rtak4.Jason', True, None),
    # ... and more
]

定义一个属于typing.NamedTuple子类的类与使用namedtuple()函数有相同的结果,除了语法更简单之外,您可以为字段添加类型,还可以选择添加docstring和其他属性或方法(几乎任何不是类型暗示属性或名称复制方法的东西都可以)。

现在,这种类型的暗示机器将对所期望的有更多的了解。现在不仅可以清楚地知道列表将包含哪种类型的实例,上面还记录了命名的tuple类支持哪些属性以及这些属性的类型。我对这些类型可能是什么做了一些有根据的猜测。我在这里还使用了python的pep-8样式约定的名称,因此命名的tuple属性都使用小写的_和下划线("snake_case"),而不是camelcase。后者应该只用于类名。