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 overriding 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')
Answer from Arne on Stack Overflow
Top answer
1 of 7
85

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 overriding 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')
2 of 7
41

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.

import dataclasses

@dataclasses.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)

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})
🌐
Reddit
reddit.com › r/learnpython › is it possible to ignore some fields when creating a python dataclass from a .csv?
r/learnpython on Reddit: is it possible to ignore some fields when creating a Python dataclass from a .csv?
September 4, 2024 -

Example code below. This works, but only if the .csv has only name, age, and city fields. If the .csv has more fields than the dataclass has defined, it throws an error like: TypeError: Person.__init__() got an unexpected keyword argument 'state'

Is there a way to have it ignore extra fields? I'm trying to avoid having to remove the fields first from the .csv, or iterate row by row, value by value...but obvs will do that if there's no 'smart' way to ignore. Like, wondering if we can pass desired fields to csv.DictReader? I see it has a fieldnames parameter, but the docs seem to suggest that is for generating a header row when one is missing (meaing, I'd have to pass a value for each column, so I'm back where I started)

Thanks!

import csv
from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int
    city: str

with open('people.csv', 'r') as f:
    reader = csv.DictReader(f)
    people = [Person(**row) for row in reader]

print(people)
Top answer
1 of 6
15
Is there a way to have it ignore extra fields? Sure, but you have to actually do it. Out of curiosity, did you find this bit of code, or did you create it yourself? The reason I ask is that using **row is a slightly more advanced Python expression and it would make sense why you're having this problem if you grabbed that part without understanding it. So first, let's break down what it's doing. The list comprehension is functionally similar to doing an operation on a loop. So what happens if we take this code and just look at row? people = [row for row in reader] You will probably see something like this if you run this code with just the three columns: [{'name': 'John Doe', 'age': '25', 'city': 'Houston'}, {'name': 'Beth Doe', 'age': '22', 'city': 'San Francisco'}] This is actually the same data the DictReader gives us. So what does the asterisk do? This is somewhat complicated, but it essentially breaks it into a tuple (single asterisk) or dictionary (double asterisk). For example, check this code based on the reader: for person in reader: print(*person) # Output name age city name age city What's happening here is that each key value is being printed out. Trying **person won't work, because it's trying to push a dictionary into print, but basically it creates arguments with key/value pairs, similar to using var=None in a parameter list for a function, where this would be `{"var": None} in dictionary format. Now that we know that, let's look back at your original code: people = [Person(**row) for row in reader] That Person(**row) is the cause of your error: DictReader is going to read every heading, so if you have 4 headings, such as state being including, it's equivalent to doing something like this: Person(name="name", age="age", city="city", state="state") The problem, of course, is that the Person dataclass doesn't have a state property, so this is undefined behavior. How can you fix this, then? Assuming you only want those three elements to represent a person, you'll need to skip the list comprehension method and do your loop manually, ignoring the fields you don't need. For example, something like this: people = [] for person in reader: new_person = Person( name = person["name"], age = int(person["age"]), city = person["city"], ) people.append(new_person) There are other ways to do this, of course, but this is the simplest. Essentially, you loop through each row, and create a new Person object with just the data from that row you want, and then you append that to a list. This will give you the same core data as your previous list comprehension but will ignore anything that isn't a row you want.
2 of 6
3
If your CSV has variable columns you either need different dataclasses for each kind or you shouldn't use them - rows with different columns are, notionally, different types of things when you're mapping rows to classes.
🌐
Python.org
discuss.python.org › python help
Dataclasses: subclassing a dataclass without its fields inherited as init-fields - Python Help - Discussions on Python.org
August 12, 2024 - I was wondering if it would be possible to allow subclassing a dataclass without automatically including its fields in Subclass.__init__ (in some sense, hiding the inherited fields). When subclassing the dataclass AB below to create CD, the fields of AB become fields of CD, automatically included ...
🌐
GitHub
github.com › samuelcolvin › pydantic › issues › 986
Pydantic dataclasses do not respect the extra-fields in Config ...
November 9, 2019 - pydantic.dataclasses.dataclass's arguments are the same as the standard decorator, except one extra keyword argument config which has the same meaning as Config. In particular I would like to ignore extra fields when initialising the object. The documentation suggests that the default behaviour is Extra.ignore, but it does not seem to work.
Author   mvalkon
🌐
Pydantic
docs.pydantic.dev › 2.0 › usage › dataclasses
Dataclasses - Pydantic
Pydantic dataclasses do not support extra='allow', where extra fields passed to the initializer would be stored as extra attributes on the dataclass. extra='ignore' is still supported for the purpose of ignoring unexpected fields while parsing data; they just won't be stored on the instance.
🌐
Pydantic
docs.pydantic.dev › latest › concepts › dataclasses
Dataclasses - Pydantic Validation
While Pydantic dataclasses support ... may prevail. For example, any extra fields present on a Pydantic dataclass with extra set to 'allow' are omitted in the dataclass' string representation....
🌐
Readthedocs
dataclass-factory.readthedocs.io › en › latest › extended.html
Extended usage — dataclass-factory documentation
It will ignore all fields which are not described in name mapping. More simplified case is to skip so-called internal use fields, those fields which name starts with underscore. You can skip them from parsing and serialization using skip_internal option of schema. It is disabled by default.
🌐
GitHub
github.com › pydantic › pydantic › discussions › 7362
Support for dataclass `extra="allow"` · pydantic/pydantic · Discussion #7362
Are there additional caveats to be aware of in addition to the absence of these extra fields in __str__? Thanks! ... from pydantic.dataclasses import dataclass @dataclass(config=dict(extra="allow")) class Example: ... obj = Example(a=1, b=2) print(obj) print(f"Extra: a={obj.a}, b={obj.b}") This script yields the following output when running with the latest pydantic==2.3.0: ... With extra="forbid", the above script fails with ValidationError on instantiation of the Example object with extra kwargs a and b. With extra="ignore" or no extra config (default is ignore), the Example object is successfully instantiated, but the script fails with AttributeError when obj.a and obj.b are accessed.
Author   pydantic
Find elsewhere
🌐
Python
docs.python.org › 3 › library › dataclasses.html
dataclasses — Data Classes
def is_dataclass_instance(obj): return is_dataclass(obj) and not isinstance(obj, type) ... A sentinel value signifying a missing default or default_factory. ... A sentinel value used as a type annotation. Any fields after a pseudo-field with the type of KW_ONLY are marked as keyword-only fields. Note that a pseudo-field of type KW_ONLY is otherwise completely ignored.
🌐
CSDN
devpress.csdn.net › python › 6304544f7e66823466199f0d.html
How does one ignore extra arguments passed to a dataclass?_python_Mangs-Python
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(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)
🌐
Python Morsels
pythonmorsels.com › customizing-dataclass-fields
Customizing dataclass fields - Python Morsels
October 23, 2024 - This is a tool that the dataclasses module provides for defining fields while customizing their behavior. Now when we make new instances of this class, we'll see that each one called Python's list function to get an independent empty list:
🌐
Python.org
discuss.python.org › ideas
Remove attributes from asdict method when dataclass field(repr=False) - Ideas - Discussions on Python.org
March 18, 2023 - Hello, as I was trying to not use some attributes from a dataclass when creating a pandas.DataFrame, I noticed that even though the specific attribute was set as field(repr=False), it persisted in the data frame. It wou…
🌐
Readthedocs
dataclass-wizard.readthedocs.io
Why Dataclass Wizard? — Dataclass Wizard 0.39.1 documentation
The default behavior is to ignore any unknown or extraneous JSON keys that are encountered when from_dict or from_json is called, and emit a “warning” which is visible when debug mode is enabled (and logging is properly configured). An unknown key is one that does not have a known mapping to a dataclass field...
🌐
Stack Overflow
stackoverflow.com › questions › tagged › python-dataclasses
Frequent 'python-dataclasses' Questions - Stack Overflow
My primary goal is to follow whatever standard other exception classes have, so that (for instance) any extra string I include in the ... ... PEP 557 introduces data classes into the Python standard library. It says that by applying the @dataclass decorator shown below, it will generate "among other things, an __init__()".
🌐
eTechtips
etechtips.com › 2024 › 07 › 31 › python-dealing-with-unknown-fields-in-dataclass
eTechtips » Python: Dealing with unknown fields in dataclass
July 31, 2024 - from dataclasses import dataclass from dataclasses import fields def filter_unexpected_fields(cls): original_init = cls.__init__ def new_init(self, *args, **kwargs): expected_fields = {field.name for field in fields(cls)} cleaned_kwargs = {key: value for key, value in kwargs.items() if key in expected_fields} unknown_kwargs = {key: value for key, value in kwargs.items() if key not in expected_fields} original_init(self, *args, **cleaned_kwargs) # Handle unknown fields (optional) if unknown_kwargs: # Log a warning or raise an exception based on your needs print(f"Warning: Unknown fields found: {unknown_kwargs}") cls.__init__ = new_init return cls @filter_unexpected_fields @dataclass class Application: id: int name: str a1 = { 'id': 1, 'name': 'WebGoat',"runs":5} app = Application(**a1)
🌐
PyPI
pypi.org › project › dataclass-wizard
dataclass-wizard · PyPI
The default behavior is to ignore any unknown or extraneous JSON keys that are encountered when from_dict or from_json is called, and emit a “warning” which is visible when debug mode is enabled (and logging is properly configured). An unknown key is one that does not have a known mapping to a dataclass field...
      » pip install dataclass-wizard
    
Published   Jan 06, 2026
Version   0.39.1
🌐
PyPI
pypi.org › project › dataclassy
dataclassy · PyPI
Use Hashed, Internal or factory to replicate its functions · there's no InitVar. Simply add arguments to __post_init__ there's no need for ClassVar. Simply omit the field's type hint to ignore it
      » pip install dataclassy
    
Published   Jan 14, 2023
Version   1.0.1
🌐
Florimond Manca
florimond.dev › en › posts › 2018 › 10 › reconciling-dataclasses-and-properties-in-python
Reconciling Dataclasses And Properties In Python - Florimond Manca
However, @dataclass now generates other boilerplate code and magic methods using _wheels, which is problematic. >>> car = Vehicle(wheels=4) setting wheels to 4 >>> car Vehicle(_wheels=4) # 😕 · Digging deeper into the docs, I found that one could fine-tune the field generation behavior using the field() function.