【问题标题】:Type hint for a module containing constants包含常量的模块的类型提示
【发布时间】:2021-05-11 23:46:06
【问题描述】:

我有一个 config.py 文件,其中有一个常量列表,例如:

config.py
NAME = 'John'
AGE = 23

在另一个文件中,我将此文件作为模块导入,然后将其作为参数传递给其他函数。我使用 ModuleType 作为这个参数的类型。

import config
from types import ModuleType
def f1(config: ModuleType) -> None:
    print(config.NAME)

问题是我运行pyright linter时,报错:

 79:30 - error: Cannot access member "NAME" for type "ModuleType"
    Member "NAME" is unknown (reportGeneralTypeIssues)

输入提示配置以避免这些错误的正确方法是什么?谢谢!

【问题讨论】:

  • 我正在尝试重新创建它以进行测试,但我无法在任何地方找到 typing.ModuleType。我也看过文档,但也没有。你是怎么得到你的?
  • 因为打字时没有ModuleTypefrom types import ModuleType。而且从types导入ModuleType后没有发现问题。
  • @12944qwerty 是的,应该是 types 而不是 typing
  • @m.i.cosacak 是的,我发现了很多。但不知何故,OP 能够从打字中得到它......除非 linter 没有认识到 ModuleType 不是来自打字。 OP 是使用 python 还是仅通过 linter 运行文件?
  • 嗯,我刚刚通过使用types 导入测试了它,它似乎可以工作。我认为这个问题可以通过错字修复来回答,对吗?

标签: python pyright


【解决方案1】:

到目前为止,处理这个问题的最简单和最方便的方法是不注释 config 参数,或将其注释为 Any。您可以提供更具体的注释,但它会变得非常尴尬。

您现有注释的问题是您的f1 被注释为将任意模块作为参数,并且任意模块可能没有NAME 属性。 (另外,ModuleTypetypes 中,而不是 typing。)f1 的正确、特定注释将指定它需要带有 NAME 属性的内容,您可以使用自定义协议类指定该属性:

import typing

class HasName(typing.Protocol):
    NAME: str

def f1(config: HasName) -> None:
    print(config.NAME)

但是您必须为您想要在config 中定义的所有内容执行此操作,如果您想在config 中允许可选配置定义,这将变得更加尴尬。

另外,如果您现在尝试将 config 作为参数传递给 f1,它仍然不起作用,因为当您将模块作为参数传递时,mypy 将其视为只是一个通用模块,不考虑它的内容。 (我不知道 pyright 是做什么的,但这就是 mypy 处理它的方式。)你必须明确地转换 config:

f1(typing.cast(HasName, config))

这是非常尴尬的。另外,一旦你有了这个演员,即使config没有NAME属性,mypy也不会报告错误,所以你根本没有安全感这个尴尬的工作。

【讨论】:

  • 将类型设置为 Any 似乎已经解决了问题。谢谢。
【解决方案2】:

事实证明,所有模块都是types.ModuleType 的子类型,因此是typing.ModuleType。因此,您想要的是:

def f1(config: config) -> None:
    print(config.NAME)

第一个config只是一个形式参数,第二个指的是模块名称。 typing 模块实际上会导入成员,并且一切正常。

这确实让我想知道这有什么意义。如果必须导入模块才能定义函数,那为什么还要将其作为参数传递呢?

【讨论】:

  • 不,模块是types.ModuleType实例,而不是子类型。模块不是类型。
  • 如果您尝试将模块指定为类型,mypy reports error: Module "whatever" is not valid as a type
  • 好的,我知道我在尝试这个时哪里出错了。我包含的代码运行,但它不正确。也许我应该把它作为一个坏例子。
猜你喜欢
  • 2020-03-19
  • 1970-01-01
  • 2012-12-24
  • 2019-09-21
  • 2019-04-12
  • 1970-01-01
  • 2012-08-14
  • 2021-12-31
  • 1970-01-01
相关资源
最近更新 更多