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

时间:2019-02-13 19:51:31

标签: python python-3.x python-dataclasses

我想创建一个config dataclass,以简化对特定环境变量的白名单和访问(键入os.environ['VAR_NAME']相对于config.VAR_NAME是乏味的)。因此,我需要忽略dataclass的{​​{1}}函数中未使用的环境变量,但是我不知道如何提取默认__init__以便将其包装为例如还包含__init__作为参数之一的函数。

*_

运行此命令可以给我import os from dataclasses import dataclass @dataclass class Config: VAR_NAME_1: str VAR_NAME_2: str config = Config(**os.environ)

3 个答案:

答案 0 :(得分:0)

我只提供一个明确的__init__而不是使用自动生成的@dataclass class Config(init=False): 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})

343  2224 S, 5434443 X, 5434 3434 T....

答案 1 :(得分:0)

在将参数列表传递给构造函数之前先对其进行清理,这可能是最好的方法。但我建议不要编写自己的__init__函数,因为数据类的__init__还会执行其他一些方便的操作,而这些操作会因覆盖而丢失。

另外,由于参数清除逻辑与类的行为紧密相关,并返回一个实例,因此将其放入classmethod中可能是有道理的:

from dataclasses import dataclass

@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 cls.__annotations__})

# 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')

答案 2 :(得分:0)

我结合了两个答案; setattr可以成为性能杀手。自然,如果字典在数据类中没有某些记录,则需要为其设置字段默认值。

from __future__ import annotations
from dataclasses import field, fields, dataclass

@dataclass()
class Record(object):
    name: str
    address: str
    zip: str = field(default=None)  # won't fail if dictionary doesn't have a zip key

    @classmethod
    def create_from_dict(cls, dict_) -> Record:
        class_fields = {f.name for f in fields(cls)}
        return Record(**{k: v for k, v in dict_.items() i k in class_fields})