如何忽略传递给数据类的额外参数?

新手上路,请多包涵

I’d like to create a config dataclass in order to simplify whitelisting of and access to specific environment variables (typing os.environ['VAR_NAME'] is tedious relative to config.VAR_NAME )。因此,我需要忽略我的 dataclass__init__ 函数中未使用的环境变量,但我不知道如何提取默认值 __init__ 例如,它带有一个函数,该函数还包括 *_ 作为参数之一。

 import os
from dataclasses import dataclass

@dataclass
class Config:
    VAR_NAME_1: str
    VAR_NAME_2: str

config = Config(**os.environ)

运行这个给我 TypeError: __init__() got an unexpected keyword argument 'SOME_DEFAULT_ENV_VAR'

原文由 Californian 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

我只想提供一个明确的 __init__ 而不是使用自动生成的。循环体只设置识别值,忽略非预期值。

请注意,直到稍后,这才会抱怨没有默认值的缺失值。

 @dataclass(init=False)
class Config:
    VAR_NAME_1: str
    VAR_NAME_2: str

    def __init__(self, **kwargs):
        names = set([f.name for f in dataclasses.fields(self)])
        for k, v in kwargs.items():
            if k in names:
                setattr(self, k, v)

或者,您可以将过滤环境传递给默认值 Config.__init__

 field_names = set(f.name for f in dataclasses.fields(Config))
c = Config(**{k:v for k,v in os.environ.items() if k in field_names})

原文由 chepner 发布,翻译遵循 CC BY-SA 4.0 许可协议

在将参数列表传递给构造函数之前清理参数列表可能是最好的方法。不过,我建议不要编写您自己的 __init__ 函数,因为数据类 __init__ 会做一些其他方便的事情,您将通过覆盖它而失去这些事情。

此外,由于参数清理逻辑与类的行为紧密绑定并返回一个实例,因此将其放入 classmethod 可能有意义:

 from dataclasses import dataclass
import inspect

@dataclass
class Config:
    var_1: str
    var_2: str

    @classmethod
    def from_dict(cls, env):
        return cls(**{
            k: v for k, v in env.items()
            if k in inspect.signature(cls).parameters
        })

# usage:
params = {'var_1': 'a', 'var_2': 'b', 'var_3': 'c'}
c = Config.from_dict(params)   # works without raising a TypeError
print(c)
# prints: Config(var_1='a', var_2='b')

原文由 Arne 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题