In our previous post covering introduction to Python dataclass, we understood the basics of a dataclass and its advantages over normal classes. In this post, we will dive deeper into dataclasses and understand various parameters that can be used with dataclasses.
When we use the dataclass decorator, we can provide the following attributes, with each being used for including some special function:
-
init parameter
-
repr parameter
-
eq parameter
-
order parameter
-
unsafe_hash parameter
-
frozen parameter
Following is the syntax for it:
@dataclasses.dataclass(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
Let us cover every parameter that has been mentioned in the above dataclass.
1. The init parameter
When the init parameter is set to True, it indicates that a default constructor has to be added in the dataclass. It behaves in the same way as an __init__
method would behave if it were explicitly defined in the class. If the init value is set to False, a default constructor won't be created.
Time for an example:
from dataclasses import dataclass
@dataclass(init = False)
class data_class():
title: str
value : int
#Creating a dataclass object
class_instance = data_class("Studytonight",
"12")
Output:
TypeError: data_class() takes no arguments
Why is this the output?
That is because the init
parameter has been set to False as a result the default constructor hasn't been created which would have initialized the class instance with values specified.
On the other hand, if the value of init
is specified as True in the above code, the output would be:
data_class(title='Studytonight', value='12')
2. The repr parameter
When the repr
parameter is set to True, it represents the data present in the dataclass in a neat and readable manner. It behaves in the same way as the __repr__
method(internally this method is added to the class) would behave it if were explicitly defined. If it were set to False, it outputs the hash value of the object in memory.
Time for an example:
from dataclasses import dataclass
@dataclass(repr = True)
class data_class():
title: str
value : int
#Creating a dataclass object
class_instance = data_class("Studytonight",
"12")
print(class_instance)
Output:
data_class(title='Studytonight', value='12')
If the repr
parameter to the dataclass decorator was set to False, it would output the below line:
<__main__.data_class object at 0x0000020D33B4CA90>
3. The eq parameter
If the eq
parameter in the dataclass decorator is set to True, it compares the contents of the two instances (of the same class using ==
or !=
) and returns True or False depending on whether or not the contents are same. It behaves in the same way as an __eq__
method would behave it if were explicitly defined.
Time for an example:
from dataclasses import dataclass
@dataclass(eq = True)
class data_class():
title: str
value : int
#Creating a dataclass object
class_instance_1 = data_class("Studytonight",
"12")
class_instance_2 = data_class("Studytonight",
"12")
check_for_equality = class_instance_1==class_instance_2
check_for_inequality = class_instance_1!=class_instance_2
print(check_for_equality)
print(check_for_inequality)
Output:
True
False
Since the eq
parameter has been set to True, the contents of the instances are compared.
If the eq
parameter was set to False, the output would be:
False
True
This is because their hash representation (based on the location at which the values of instances are present) are compared and obviously the two instances are stored in two different memory locations, hence the result would be False.
4. The order parameter
The order
parameter comprises of >
, <
, <=
, and >=
operators. When the order
parameter is set to True, the attributes of every instance is compared to the other instance in question.
Time for an example:
from dataclasses import dataclass
@dataclass(order = True)
class data_class():
title: str
value : int
#Creating a dataclass object
class_instance_1 = data_class("Studytonight",
"13")
class_instance_2 = data_class("Studytonight",
"12")
greater_checking = class_instance_1 > class_instance_2
lesser_or_equal_checking = class_instance_1 <= class_instance_2
print(greater_checking)
print(lesser_or_equal_checking)
Output:
True
False
When the order
parameter is set to False, a TypeError
is shown.
Traceback (most recent call last):
File "<ipython-input-20-258d272e70dd>", line 14, in <module>
greater_checking = class_instance_1>class_instance_2
TypeError: '>' not supported between instances of 'data_class' and 'data_class'
When we specify the order
parameter as True, then the special methods __lt__
(for less than), __gt__
(for greater than) etc are added to the dataclass by default.
5. The unsafe_hash parameter
The unsafe_hash
parameter refers to granting permission for the generation of a hash value for mutable objects. In reality, the mutable objects (objects whose values can be changed) can't have a hash representation. This means, even by using the hash method, mutable object's hash values shouldn't be generated.
But upon setting the unsafe_hash
parameter as True, it generates a hash value for objects of the dataclass (which is mutable). As the parameter name itself suggests, it is unsafe to generate a hash representation for a mutable object.
Internally, this adds the __hash()__
method to the the dataclass.
Time for an example:
from dataclasses import dataclass
@dataclass(unsafe_hash = False )
class data_class():
title: str
value : int
#Creating a dataclass object
class_instance_1 = data_class("Studytonight",
"14")
print(class_instance_1)
print(hash(class_instance_1))
Output:
data_class(title='Studytonight', value='14')
Traceback (most recent call last):
File "<ipython-input-28-97bf774fdaac>", line 13, in <module>
print(hash(class_instance_1))
TypeError: unhashable type: 'data_class'
When the parameter unsafe_hash
is set to True, the output is:
data_class(title='Studytonight', value='14')
1769436267547038324
Every time the values of the attributes in the dataclass is changed, the hash representation of it changes when unsafe_hash
is set to True.
Now your question might be, what is the point of an object being immutable?
Well, a mutable object can be changed to become immutable by setting the frozen
parameter to True (the frozen
parameter has been explained in the below section). This way, when the unsafe_hash
parameter is set to True, a hash representation is generated for an immutable object.
On the other hand, if the frozen
is set to False and unsafe_hash
is True, the dataclass must be used extremely carefully since it will have the ability to generate a hash value for a mutable object.
Also, if the eq
parameter is set as True and frozen
parameter is also set as True then a __hash__
method is added to the dataclass by default.
6. The frozen parameter
If this paramter is set to True, once the values of an object are set or initialized, their values can't be changed. The values freeze. This works on the same lines of const
keyword in C++ and final
keyword in Java. When this parameter is set to True, once a value is defined, it can't be changed. If any efforts are made to change the value, a FrozenInstanceError
is displayed.
Time for an example:
from dataclasses import dataclass
@dataclass(frozen = True )
class data_class():
title: str
value : int
#Creating a dataclass object
class_instance_1 = data_class("Studytonight",
"13")
print(class_instance_1) #Before reassigning value
class_instance_1. value = 12
print(class_instance_1) #After reassigning a new value
Output:
data_class(title='Studytonight', value='13')
Traceback (most recent call last):
File "<ipython-input-21-be74e685c8ae>", line 13, in <module>
class_instance_1. value = 12
File "<string>", line 3, in __setattr__
FrozenInstanceError: cannot assign to field 'value'
When the frozen
parameter is set to False, the dataclass behaves normally, and the values of the class can be changed. The above code (when frozen = False
) gives below output:
data_class(title='Studytonight', value='13')
data_class(title='Studytonight', value=12)
Conclusion
In this post, we understood how various parameters supplied to the dataclass change the working of various methods inside the dataclass. In the next post, we will learn about the field function of dataclass in Python. So stay tuned.
You may also like: