2

It's useful to be able to create frozen dataclasses. I'm wondering if there is a way to do something similar for regular python classes (ones with an __init__ function with complex logic possibly). It would be good to prevent modification after construction in some kind of elegant way, like frozen dataclasses.

Allen Wang
  • 2,426
  • 2
  • 24
  • 48
  • 1
    Well, basically, don't present any modifier methods and make attributes at least protected… – deceze Nov 04 '22 at 06:29
  • Does this answer your question? [Dataclass-style object with mutable and immutable properties?](https://stackoverflow.com/questions/58532383/dataclass-style-object-with-mutable-and-immutable-properties) – Alexey S. Larionov Nov 04 '22 at 06:33
  • 1
    just dont make any of your attributes "public" and expose everything through properties that dont have a `@setter`. – juanpa.arrivillaga Nov 04 '22 at 08:01
  • Note, dataclasses only prevent accidental modifications, which is the best you can hope for in user-defined classes. – juanpa.arrivillaga Nov 04 '22 at 08:02
  • It's unspecific. Give an example demonstrating features you want. Why not using a data class or a class derived from the ```tuple``` or a ```collections.namedtuple()```? – relent95 Nov 04 '22 at 12:54

1 Answers1

2

yes.

All attribute access in Python is highly customizable, and this is just a feature dataclasses make use of.

The easiest way to control attribute setting is to create a custom __setattr__ method in your class - if you want to be able to create attributes during __init__ one of the ways is to have an specific parameter to control whether each instance is frozen already, and freeze it at the end of __init__:

class MyFrozen:
   _frozen = False
   def __init__(self, ...):
       ...
       self._frozen = True

   def __setattr__(self, attr, value):
       if getattr(self, "_frozen"):
            raise AttributeError("Trying to set attribute on a frozen instance")
       return super().__setattr__(attr, value) 
jsbueno
  • 99,910
  • 10
  • 151
  • 209