How does one ignore extra arguments passed to a data class?
Cleaning the argument list before passing it to the constructor is probably the best way to go about it. I'd advice against writing your own __init__
function though, since the dataclass' __init__
does a couple of other convenient things that you'll lose by overwriting it.
Also, since the argument-cleaning logic is very tightly bound to the behavior of the class and returns an instance, it might make sense to put it into a 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')
I would just provide an explicit __init__
instead of using the autogenerated one. The body of the loop only sets recognized value, ignoring unexpected ones.
Note that this won't complain about missing values without defaults until later, though.
@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)
Alternatively, you can pass a filtered environment to the default 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})