Prerequisite: Data Classes in Python | Set 1
In this post, we will discuss how to modify the default constructor which dataclass
module virtually makes for us.
dataclass()
decorator –
@dataclasses.dataclass(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
By changing the values of these parameters, we can modify the behavior and functioning of the default constructor been made for our DataClasses.
init: This parameter specifies that there should be a default constructor or not.
True (default): There will be a default Constructor. False : There won't be a default Constructor.
from dataclasses import dataclass @dataclass (init = False ) class GfgArticle(): title: str author: str language: str upvotes: int # A DataClass object article = GfgArticle( "DataClasses" , "vibhu4agarwal" , "Python" , 0 ) |
TypeError: object() takes no parameters
repr : This parameter specifies how the __repr__() function will behave. False value corresponds to hash value representation of the object in memory. True value corresponds to DataClass representation of the object.
from dataclasses import dataclass @dataclass ( repr = False ) class GfgArticle(): title: str author: str language: str upvotes: int # A DataClass object article = GfgArticle( "DataClasses" , "vibhu4agarwal" , "Python" , 0 ) print (article) |
Output:
__main__.GfgArticle object at 0x7f391b7ddbe0
eq : This parameter is used to specify the operation performed in comparison when two DataClasses are compared for equality using == or != operators. eq takes in boolean values.
from dataclasses import dataclass @dataclass ( repr = False , eq = False ) class GfgArticle(): title: str author: str language: str upvotes: int # Two DataClass objects dClassArticle1 = GfgArticle( "DataClasses" , "vibhu4agarwal" , "Python" , 0 ) dClassArticle2 = GfgArticle( "DataClasses" , "vibhu4agarwal" , "Python" , 0 ) equal = dClassArticle1 = = dClassArticle2 print ( 'Classes Equal:' , equal) |
Output:
__main__.GfgArticle object at 0x7ff501c63c18 __main__.GfgArticle object at 0x7ff501c63ba8 Classes Equal: False
When eq=False, the two object are compared using their hash based on its location in memory like two normal objects. Since the two objects have different hash representation, their equality returns False.
order : Comparison between two DataClasses are not only restricted only to equality, but also supports >, >=, < and <= operators when order=True is set in argument parameter.
The comparison between objects is based on the comparison between their corresponding attributes, which is done one by one starting from the first one.
from dataclasses import dataclass @dataclass (order = True ) class A(): var1: int var2: str var3: float obj1 = A( 1 , "GeeksForGeeks" , 7.0 ) obj2 = A( 2 , "GeeksForGeeks" , 7.0 ) obj3 = A( 1 , "GfG" , 7.0 ) obj4 = A( 1 , "GeeksForGeeks" , 8.0 ) print (obj1 > obj2) print (obj1 < obj3) print (obj1 > = obj4) |
Output:
False True False
frozen : This sets all the variables in the DataClass as one-time initializable that is once initialized, it cannot be reassigned a new value. C++ users can relate this to const and Java users can relate this to final keyword.
from dataclasses import dataclass @dataclass (frozen = True ) class GfgArticle(): title: str author: str language: str upvotes: int dClassArticle = GfgArticle( "DataClasses" , "vibhu4agarwal" , "Python" , 0 ) print (dClassArticle) dClassArticle.upvotes = 100 print (dClassArticle) |
GfgArticle(title=’DataClasses’, author=’vibhu4agarwal’, language=’Python’, upvotes=0)
Traceback (most recent call last):
File “dClass.py”, line 16, in <module>
dClassArticle.upvotes = 100
File “<string>”, line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field ‘upvotes’
unsafe_hash : Generally, mutable objects in python are Unhashable. This means their hash cannot be generated using the hash() function of Python.
Since any class objects including DataClass objects’ values can change, they are mutable. Hence they shouldn’t be able to produce any hash value.
from dataclasses import dataclass @dataclass class GfgArticle(): title: str author: str language: str upvotes: int dClassArticle = GfgArticle( "DataClasses" , "vibhu4agarwal" , "Python" , 0 ) print (dClassArticle) print ( hash (dClassArticle)) |
GfgArticle(title=’DataClasses’, author=’vibhu4agarwal’, language=’Python’, upvotes=0)
Traceback (most recent call last):
File “dClass.py”, line 15, in <module>
print(hash(dClassArticle))
TypeError: unhashable type: ‘GfgArticle’
However frozen=True sets the variables one-time initializable and hence makes the object immutable. This safely generates a hash for the DataClass object.
from dataclasses import dataclass @dataclass (frozen = True ) class GfgArticle(): title: str author: str language: str upvotes: int dClassArticle = GfgArticle( "DataClasses" , "vibhu4agarwal" , "Python" , 0 ) print (dClassArticle) print ( hash (dClassArticle)) |
Output:
GfgArticle(title=’DataClasses’, author=’vibhu4agarwal’, language=’Python’, upvotes=0)
9111021502060859577
unsafe_hash forces a DataClass which is still mutable to generate a hash.
This case comes into use when logically, we know that once initialized, we aren’t going to change the Dataclass attributes’ values. But it comes down to the question of Can they be changed? or in other words, Is the DataClass is not frozen or not? While using unsafe_hash, if the DataClass is not frozen, then DataClass generates an unsafe hash, assuming that the class is frozen and then the programmer has to further use this very carefully.
from dataclasses import dataclass @dataclass (unsafe_hash = True ) class GfgArticle(): title: str author: str language: str upvotes: int dClassArticle = GfgArticle( "DataClasses" , "vibhu4agarwal" , "Python" , 0 ) print (dClassArticle) print ( hash (dClassArticle)) |
Output:
GfgArticle(title=’DataClasses’, author=’vibhu4agarwal’, language=’Python’, upvotes=0)
8924105619418522237