In Python, "frozen" means an object cannot be modified. For example, consider set and frozenset:

>>> s = set((1, 2, 3))
>>> s
{1, 2, 3}
>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> fs = frozenset((1, 2, 3))
>>> fs
frozenset({1, 2, 3})
>>> fs.add(4)
...
AttributeError: 'frozenset' object has no attribute 'add'

Likewise, creating a dataclass with frozen=True means its instances are frozen and cannot be changed.

Be aware that frozen only applies to the dataclass instance itself – a frozen dataclass can contain mutable items such as lists, and a regular dataclass can contain frozen/immutable items such as tuples.


The point of frozen objects is to avoid accidental modification, and to guarantee a consistent value.

  • The former is advantageous to avoid bugs. When an object is not intended to be modified, making it frozen reveals accidental modification via an immediate error.
  • The latter allows use as immutable object, for example the keys of a dict. A frozen dataclass is by default hashable and suitable as a dict key.
from dataclasses import dataclass

@dataclass(frozen=True)
class Frozen:
    x: int
    y: int

named_points = {Frozen(0, 0): "Origin"}

Note that hashability does not just depend on the dataclass but is recursive – a frozen dataclass containing a list is not hashable, because the list is not hashable.

Answer from MisterMiyagi on Stack Overflow
🌐
Python
docs.python.org › 3 › library › dataclasses.html
dataclasses — Data Classes
3 weeks ago - Raised when an implicitly defined __setattr__() or __delattr__() is called on a dataclass which was defined with frozen=True.
Discussions

Idiomatic way to create a frozen + mutable dataclass pair?
A mutable dataclass is easy: @dataclasses.dataclass class Mutable_Foo: ham: str eggs: int A frozen dataclass is easy: @dataclasses.dataclass(frozen=True) class Frozen_Foo: ham: str eggs: int But I frequently want to use both Mutable_Foo and Frozen_Foo in the same codebase, with exactly the ... More on discuss.python.org
🌐 discuss.python.org
0
0
November 29, 2024
`dataclass(frozen=True)` not working with default `Final` qualifier
Bug Report When using Final type hint in combination with dataclass(frozen=True), mypy displays an error. This error disappears either if frozen=True is removed or the type of Final is provided. To Reproduce from dataclasses import datac... More on github.com
🌐 github.com
0
January 29, 2025
frozen dataclass inheritance is not strictly checked in multiple inheritance
The dataclass inheritance hierarchy is supposed to require all classes to be either frozen or non frozen, this works properly for checking that an unfrozen class does not inherit from any frozen classes, but it allows frozen classes to inherit from unfrozen ones as long as there's at least ... More on github.com
🌐 github.com
5
September 14, 2023
dataclass with `frozen=True` with `init=False` can't be instantiated
Creating a dataclass that has frozen=True and a field with init=False makes a class that throws a dataclasses.FrozenInstanceError: cannot assign to field 'a_field' error when attempting to ... More on github.com
🌐 github.com
2
October 14, 2019
🌐
Python.org
discuss.python.org › python help
Idiomatic way to create a frozen + mutable dataclass pair? - Python Help - Discussions on Python.org
November 29, 2024 - A mutable dataclass is easy: @dataclasses.dataclass class Mutable_Foo: ham: str eggs: int A frozen dataclass is easy: @dataclasses.dataclass(frozen=True) class Frozen_Foo: ham: str eggs: int But I frequently …
🌐
Rednafi
rednafi.com › python › statically enforcing frozen data classes in python
Statically enforcing frozen data classes in Python | Redowan's Reflections
January 4, 2024 - You can use @dataclass(frozen=True) to make instances of a data class immutable during runtime. However, there’s a small caveat - instantiating a frozen data class is slightly slower than a non-frozen one.
🌐
Plain English
plainenglish.io › home › blog › python › why and how to write frozen dataclasses in python
Why and How to Write Frozen Dataclasses in Python
February 22, 2022 - Simply add the “frozen=True” to the decorator: @dataclass(frozen=True) and run the tests again. You will see this error: E dataclasses.FrozenInstanceError: cannot assign to field 'blocked' The problem (or the feature) is that you may not ...
Find elsewhere
🌐
GitHub
github.com › sqlalchemy › sqlalchemy › discussions › 9192
Support for mapping frozen dataclasses · sqlalchemy/sqlalchemy · Discussion #9192
One can freeze a dataclass by decorating it with @dataclass(frozen=True). The effect of this is that trying to set an attribute on a frozen dataclass will raise an exception.
Author   sqlalchemy
🌐
Rednafi
rednafi.com › python › statically_enforcing_frozen_dataclasses
https://rednafi.com/python/statically-enforcing-frozen-dataclasses/
January 4, 2024 - You can use @dataclass(frozen=True) to make instances of a data class immutable during runtime. However, there’s a small caveat—instantiating a frozen data class is slightly slower than a non-frozen one. This is because, when you enable frozen=True, Python has to generate __setattr__ and ...
🌐
GitHub
github.com › python › mypy › issues › 18567
`dataclass(frozen=True)` not working with default `Final` qualifier · Issue #18567 · python/mypy
January 29, 2025 - This error disappears either if frozen=True is removed or the type of Final is provided. ... from dataclasses import dataclass from typing import Final @dataclass class Foo: var: Final = "a" @dataclass(frozen=True) class Foo2: var: Final = "a" @dataclass(frozen=True) class Foo3: var: Final[str] = "a" foo = Foo() foo.var # OK foo2 = Foo2() foo2.var # ERROR: "Foo" not callable [operator] foo3 = Foo3() foo3.var # OK
Author   mflova
🌐
GitHub
github.com › python › cpython › issues › 109409
frozen dataclass inheritance is not strictly checked in multiple inheritance · Issue #109409 · python/cpython
September 14, 2023 - import dataclasses @dataclasses.dataclass class NotFrozen: pass @dataclasses.dataclass(frozen=True) class Frozen: pass @dataclasses.dataclass(frozen=True) class Child(NotFrozen, Frozen): pass ·
Author   Batman-q96
🌐
GitHub
github.com › ericvsmith › dataclasses › issues › 150
dataclass with `frozen=True` with `init=False` can't be instantiated · Issue #150 · ericvsmith/dataclasses
October 14, 2019 - Creating a dataclass that has frozen=True and a field with init=False makes a class that throws a dataclasses.FrozenInstanceError: cannot assign to field 'a_field' error when attempting to ...
Author   DBCerigo
🌐
Python Morsels
pythonmorsels.com › customizing-dataclass-initialization
Customizing dataclass initialization - Python Morsels
October 18, 2024 - File "<string>", line 17, in ... called for each attribute assignment. Setting frozen=True on our dataclass will override this method with one that always raises an exception....
🌐
Python Forum
python-forum.io › thread-43340.html
change dataclass to frozen at runtime
October 5, 2024 - I'm working with a dataclass that is code-generated by a tool I do not control: @dataclass class Concern: id: ConcernIDNote that the dataclass is not declared as frozen. I need this class to be frozen for the sake of Hashability, so I would like...
🌐
Medium
elshad-karimov.medium.com › pythons-dataclasses-replace-a-hidden-gem-for-immutable-data-handling-e10a82f6260b
Python’s dataclasses.replace() – A Hidden Gem for Immutable Data Handling! 🚀🐍 | by Elshad Karimov | Medium
March 26, 2025 - from dataclasses import dataclass @dataclass(frozen=True) class User: name: str age: int country: str user1 = User(name="Alice", age=30, country="USA") # ❌ This will fail since the dataclass is frozen # user1.age = 31 # ERROR: dataclasses.FrozenInstanceError
Top answer
1 of 3
10

Well, you can do it by directly modifying the __dict__ member of the instance modifying the attribute using object.__setattr__(...)1, but why??? Asking specifically for immutable and then making it mutable is... indecisive. But if you must:

from dataclasses import dataclass

@dataclass(frozen=True)
class Foo:
    id: str
    name: str
    def strip_id(self):
        object.__setattr__(self, 'id', None)

foo=Foo(10, 'bar')

>>> foo
Foo(id=10, name='bar')
>>> foo.strip_id()
>>> foo
Foo(id=None, name='bar')

Any way of doing this is probably going to seem hacky... because it requires doing things that are fundamentally the opposite of the design.

If you're using this as a signal to other programmers that they should not modify the values, the way that is normally done in Python is by prefixing the variable name with a single underscore. If you want to do that, while also making the values accessible, Python has a builtin module called property, where (from the documentation) "typical use is to define a managed attribute":

from dataclasses import dataclass

@dataclass
class Foo:
    _name: str
    @property
    def name(self):
        return self._name
    @name.setter
    def name(self, value):
        self._name = value
    @name.deleter
    def name(self):
        self._name = None

Then you can use it like this:

>>> f=Foo()
>>> f.name = "bar"
>>> f.name
'bar'
>>> f._name
'bar'
>>> del f.name
>>> f.name
>>> f._name

The decorated methods hide the actual value of _name behind name to control how the user interacts with that value. You can use this to apply transformation rules or validation checks to data before it is stored or returned.

This doesn't quite accomplish the same thing as using @dataclass(frozen=True), and if you try declaring it as frozen, you'll get an error. Mixing frozen dataclasses with the property decorator is not straightforward and I have not seen a satisfying solution that is concise and intuitive. @Arne posted this answer, and I found this thread on GitHub, but neither approach is very inspiring; if I came across such things in code that I had to maintain, I would not be very happy (but I would be confused, and probably pretty irritated).


1: Modified as per the answer by @Arne, who observed that the internal use of a dictionary as the data container is not guaranteed.

2 of 3
5

As a slight improvement over Z4-tier's solution, please use object.__setattr__ instead of self.__dict__ to manipulate attributes of a frozen dataclass. The fact that classes use a dictionary to store their attributes is just the default behavior, and dataclasses in particular will regularly use __slots__ instead because it reduces the memory footprint.

from dataclasses import dataclass

@dataclass(frozen=True)
class Foo:
    id: str
    name: str

    def strip_id(self):
        object.__setattr__(self, 'a', None)   
🌐
Pydantic
docs.pydantic.dev › latest › concepts › dataclasses
Dataclasses - Pydantic Validation
import dataclasses from pydantic import BaseModel, ConfigDict, ValidationError @dataclasses.dataclass(frozen=True) class User: name: str class Foo(BaseModel): # Required so that pydantic revalidates the model attributes: model_config = ConfigDict(revalidate_instances='always') user: User | None = None # nothing is validated as expected: user = User(name=['not', 'a', 'string']) print(user) #> User(name=['not', 'a', 'string']) try: Foo(user=user) except ValidationError as e: print(e) """ 1 validation error for Foo user.name Input should be a valid string [type=string_type, input_value=['not', 'a', 'string'], input_type=list] """ foo = Foo(user=User(name='pika')) try: foo.user.name = 'bulbi' except dataclasses.FrozenInstanceError as e: print(e) #> cannot assign to field 'name'
🌐
GitHub
github.com › python › mypy › issues › 14857
`Cannot inherit frozen dataclass from a non-frozen one` error when using pydantic `frozen=True` · Issue #14857 · python/mypy
March 8, 2023 - Bug Report Specifying frozen=True as model class kwargs for pydantic models causes the following error to be emitted from mypy: Cannot inherit frozen dataclass from a non-frozen one To Reproduce In...
Author   johnnyleitrim