首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mypy Config类

Mypy Config类
EN

Stack Overflow用户
提问于 2022-02-20 17:53:49
回答 1查看 103关注 0票数 0

我目前正在做一些工作,希望将配置从yaml加载到类中,以便指定类属性。根据我所做的工作,我有一个不同的配置类。

在类中,我预先指定了预期的参数,如下所示,然后使用BaseConfig::load_config()从文件中加载数据。这将检查类在使用setattr()分配值之前是否具有相应的属性。

代码语言:javascript
复制
class AutoencoderConfig(BaseConfig):

    def __init__(self, config_path: Path) -> None:

        super().__init__(config_path)

        self.NTRAIN: Optional[int] = None
        self.NVALIDATION: Optional[int] = None

        # ... more below

        self.load_config()

当我在其他脚本中引用AutoencoderConfig的属性时,我可能会说:config.NTRAIN。虽然这样做很好,但是Mypy不喜欢这样,并给出了以下错误:

代码语言:javascript
复制
path/to/file.py:linenumber: error: Unsupported operand types for / ("None" and "int")

出现此错误是因为在进行检查时,尚未加载来自yaml文件的值,而且类型是用self.NTRAIN: Optional[int] = None指定的。

无论如何,我可以避免这种情况,而不必将:# type: ignore放在我所引用的config类的每一行末尾吗?

有使用这样的配置类的最佳实践吗?

编辑:

解决方案:

下面@SUTerliakov提供的解决方案非常好。最后,我决定采用一种@dataclass方法:

代码语言:javascript
复制
from dataclasses import dataclass, field

@dataclass
class BaseConfig:

    _config: Dict[str, Any] = field(default_factory=dict, repr=False)

    def load_config(self, config_path: Path) -> None:
        ...


@dataclass
class AutoencoderConfig(BaseConfig):

    NTRAIN: int = field(init=False)
    NVALIDATION: int = field(init=False)

    # ... more below

这允许我将每个变量指定为field(init=False),这似乎是解决问题的一个很好、明确的方法。

EN

回答 1

Stack Overflow用户

发布于 2022-04-12 21:38:00

在调用int之后总是load_config吗?(它能保持一种状态吗?)

如果总是int,那么不要将它们标记为Optional,也不要分配None。只需在类主体中声明它们而不进行初始化:

代码语言:javascript
复制
class AutoencoderConfig(BaseConfig):
    NTRAIN: int
    NVALIDATION: int
    def __init__(self, config_path: Path):
        super().__init__(config_path)
        # Whatever else
        self.load_config()

否则,您必须在操作之前显式检查None。对于这种情况,type: ignore是一个糟糕的解决方案,因为这只会使真正的问题安静下来:Optional被用来表示变量可以是None,而不能将None除以整数,因此它可能会导致运行时问题。在这种情况下,适当的解决方案如下:

代码语言:javascript
复制
if self.NTRAIN is not None: 
    foo = self.NTRAIN / 2
else:
    raise ValueError('NTRAIN required!')
    # Or
    # foo = some_default_foo
    # If you can handle such case

如果您知道在某个点之后它不可能是零,那么最干净的就是像这样assert它:

代码语言:javascript
复制
assert self.NTRAIN is not None
foo = self.NTRAIN / 2

这两种方法都会使mypy高兴,因为NTRAIN实际上不是条件分支中的None,也不是assert之后的。

编辑:对不起,我可能误解了你的问题。load_config需要hasattr(AutoencoderConfig, 'NTRAIN')才能真正工作吗?如果是这样的话,最简单的解决方案是

代码语言:javascript
复制
class AutoencoderConfig(BaseConfig):
    NTRAIN: int = None  # type: ignore[assignment]
    NVALIDATION: int = None  # type: ignore[assignment]
    def __init__(self, config_path: Path):
        super().__init__(config_path)
        # Whatever else
        self.load_config()

您不需要任何其他类型-忽略这种方式。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71197155

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档