包含常量的模块的类型提示
Type hint for a module containing constants
我有一个 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)
输入配置提示以避免这些错误的正确方法是什么?谢谢!
事实证明,所有模块都是 types.ModuleType
的子类型,因此 typing.ModuleType
。因此,你想要的是:
def f1(config: config) -> None:
print(config.NAME)
第一个config
只是一个形式参数,第二个是按名称引用模块。 typing
模块实际上会导入成员,一切正常。
这确实让我想知道这有什么意义。如果必须导入模块才能定义函数,那么为什么要将它作为参数传递呢?
到目前为止,处理此问题的最简单和最方便的方法是不注释 config
参数,或将其注释为 Any
。您可以提供更具体的注释,但它会变得非常尴尬。
您现有注释的问题在于您的 f1
被注释为将任意模块作为参数,而任意模块可能没有 NAME
属性。 (另外 ModuleType
在 types
中,而不是 typing
。) f1
的正确、特定的注释将指定它采用具有 NAME
属性的东西,这您可以使用自定义协议指定 class:
import typing
class HasName(typing.Protocol):
NAME: str
def f1(config: HasName) -> None:
print(config.NAME)
但是你必须对你想在 config
中定义的所有内容执行此操作,如果你想在 config
中允许可选的配置定义,它会变得更加尴尬。
此外,如果您现在尝试将 config
作为参数传递给 f1
,它 仍然 不会起作用,因为当您传递一个module 作为参数,mypy 将其视为通用模块,不考虑其内容。 (我不知道 pyright 做了什么,但这就是 mypy 处理它的方式。)你必须明确地投射 config
:
f1(typing.cast(HasName, config))
这非常尴尬。另外,一旦你有了这个转换,即使 config
没有 有 NAME
属性,mypy 也不会报告错误,所以你已经这些笨拙的工作一点安全感都没有。
我有一个 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)
输入配置提示以避免这些错误的正确方法是什么?谢谢!
事实证明,所有模块都是 types.ModuleType
的子类型,因此 typing.ModuleType
。因此,你想要的是:
def f1(config: config) -> None:
print(config.NAME)
第一个config
只是一个形式参数,第二个是按名称引用模块。 typing
模块实际上会导入成员,一切正常。
这确实让我想知道这有什么意义。如果必须导入模块才能定义函数,那么为什么要将它作为参数传递呢?
到目前为止,处理此问题的最简单和最方便的方法是不注释 config
参数,或将其注释为 Any
。您可以提供更具体的注释,但它会变得非常尴尬。
您现有注释的问题在于您的 f1
被注释为将任意模块作为参数,而任意模块可能没有 NAME
属性。 (另外 ModuleType
在 types
中,而不是 typing
。) f1
的正确、特定的注释将指定它采用具有 NAME
属性的东西,这您可以使用自定义协议指定 class:
import typing
class HasName(typing.Protocol):
NAME: str
def f1(config: HasName) -> None:
print(config.NAME)
但是你必须对你想在 config
中定义的所有内容执行此操作,如果你想在 config
中允许可选的配置定义,它会变得更加尴尬。
此外,如果您现在尝试将 config
作为参数传递给 f1
,它 仍然 不会起作用,因为当您传递一个module 作为参数,mypy 将其视为通用模块,不考虑其内容。 (我不知道 pyright 做了什么,但这就是 mypy 处理它的方式。)你必须明确地投射 config
:
f1(typing.cast(HasName, config))
这非常尴尬。另外,一旦你有了这个转换,即使 config
没有 有 NAME
属性,mypy 也不会报告错误,所以你已经这些笨拙的工作一点安全感都没有。