DataClasses has been added in a recent addition in python 3.7 as a utility tool for storing data. DataClasses provides a decorator and functions for automatically adding generated special methods such as __init__() , __repr__() and __eq__() to user-defined classes.
DataClass in Python
DataClasses are like normal classes in Python, but they have some basic functions like instantiation, comparing, and printing the classes already implemented.
Installing the DataClasses module:
pip install dataclasses
The syntax of the dataclass is:
Syntax: @dataclasses.dataclass(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
Parameters:
- init: If true __init__() method will be generated
- repr: If true __repr__() method will be generated
- eq: If true __eq__() method will be generated
- order: If true __lt__(), __le__(), __gt__(), and __ge__() methods will be generated.
- unsafe_hash: If False __hash__() method is generated according to how eq and frozen are set
- frozen: If true assigning to fields will generate an exception.
DataClass module provides a handy way to make classes less wordy. Let us see the traditional approach without using DataClass.
Python3
# creating a employee class class employee: # init method or constructor def __init__( self , name, emp_id, age, city): # Instance Variable self .name = name self .emp_id = emp_id self .age = age self .city = city # magic function to return class object def __repr__( self ): return ( "employee (name={}, emp_id={}, age={}, city={} )" . format ( self .name, self .emp_id, self .age, self .city)) # magic function to return boolean def __eq__( self , check): return (( self .name, self .emp_id, self .age, self .city) = = ((check.name, check.emp_id, check.age, check.city))) # initialization the object emp1 = employee( "Satyam" , "ksatyam858" , 21 , 'Patna' ) emp2 = employee( "Anurag" , "au23" , 28 , 'Delhi' ) emp3 = employee( "Satyam" , "ksatyam858" , 21 , 'Patna' ) print ( "employee object are :" ) print (emp1) print (emp2) print (emp3) # printing new line print () # referring two object to check equality print ( "Data in emp1 and emp2 are same? " , emp1 = = emp2) print ( "Data in emp1 and emp3 are same? " , emp1 = = emp3) |
employee object are : employee (name=Satyam, emp_id=ksatyam858, age=21, city=Patna ) employee (name=Anurag, emp_id=au23, age=28, city=Delhi ) employee (name=Satyam, emp_id=ksatyam858, age=21, city=Patna ) Data in emp1 and emp2 are same? False Data in emp1 and emp3 are same? True
In the above code the biggest problem in passing the argument in __init__, __repr__, and __eq__. Each time it has to copy its properties and return the object. It is a good way of dealing with a small amount of data but supposes we have work with large data. It makes your code more complicated. So, that why DataClass will implement to make your code easier and handy.
Here are the same example, implemented in Python DataClasses.
Python3
# A basic Data Class # importing dataclass module from dataclasses import dataclass # A class for holding an employees content @dataclass class employee: # Attributes Declaration # using Type Hints name: str emp_id: str age: int city: str emp1 = employee( "Satyam" , "ksatyam858" , 21 , 'Patna' ) emp2 = employee( "Anurag" , "au23" , 28 , 'Delhi' ) emp3 = employee( "Satyam" , "ksatyam858" , 21 , 'Patna' ) print ( "employee object are :" ) print (emp1) print (emp2) print (emp3) # printing new line print () # referring two object to check equality print ( "Data in emp1 and emp2 are same? " , emp1 = = emp2) print ( "Data in emp1 and emp3 are same? " , emp1 = = emp3) |
Output:
employee object are :
employee(name=’Satyam’, emp_id=’ksatyam858′, age=21, city=’Patna’)
employee(name=’Anurag’, emp_id=’au23′, age=28, city=’Delhi’)
employee(name=’Satyam’, emp_id=’ksatyam858′, age=21, city=’Patna’)
Data in emp1 and emp2 are same? False
Data in emp1 and emp3 are same? True
In the above code, we don’t need to write a code for __init__, __repr__, and __eq__ function.
dataclasses.Field()
The field() objects describe each defined field.
Syntax: dataclasses.field(*, default=MISSING, default_factory=MISSING, repr=True, hash=None, init=True, compare=True, metadata=None)
Parameters:
- default
- default_factory
- init
- repr
- hash
- compare
- metadata
Example: Demonstration of how to view the fields of a dataclass object.
Python3
from dataclasses import dataclass # A class for holding an employees content @dataclass class employee: # Attributes Declaration # using Type Hints name: str emp_id: str age: int city: str # object of the class emp = employee( "Satyam" , "ksatyam858" , 21 , 'Patna' ) emp.__dataclass_fields__ |
Output:
Explanation of the parameters :
- default: This field is used to specify default values for this field.
Python3
# default field example from dataclasses import dataclass, field # A class for holding an employees content @dataclass class employee: # Attributes Declaration # using Type Hints name: str emp_id: str age: int # default field set # city : str = "patna" city: str = field(default = "patna" ) emp = employee( "Satyam" , "ksatyam858" , 21 ) print (emp) |
Output:
employee(name=’Satyam’, emp_id=’ksatyam858′, age=21, city=’patna’)
- default_factory: This field accepts a function and returns the initial value of the field, it must be a zero-argument.
Python3
# default factory example from dataclasses import dataclass, field def get_emp_id(): id = 2345 return id # A class for holding an employees content @dataclass class employee: # Attributes Declaration # using Type Hints name: str age: int # default factory field emp_id: str = field(default_factory = get_emp_id) city: str = field(default = "patna" ) # object of dataclass emp = employee( "Satyam" , 21 ) print (emp) |
Output:
employee(name=’Satyam’, age=21, emp_id=2345, city=’patna’)
- init : If true this field is included as a parameter to the generated __init__() method.
Python3
# init field example from dataclasses import dataclass, field # A class for holding an employees content @dataclass class employee: # Attributes Declaration # using Type Hints name: str age: int # init field emp_id: str city: str = field(init = False , default = "patna" ) # object of dataclass emp = employee( "Satyam" , "ksatyam858" , 21 ) print (emp) |
Output:
employee(name=’Satyam’, age=’ksatyam858′, emp_id=21, city=’patna’)
- repr: If true (the default), this field is included in the string returned by the generated __repr__() method.
Python3
# repr field from dataclasses import dataclass, field # A class for holding an employees content @dataclass class employee: # Attributes Declaration # using Type Hints name: str age: int emp_id: str city: str = field(init = False , default = "patna" , repr = True ) emp = employee( "Satyam" , 21 , "ksatyam858" ), print (emp) |
Output:
employee(name=’Satyam’, age=21, emp_id=’ksatyam858′, city=’patna’)
If repr is false then:
Python3
city: str = field(init = False , default = "patna" , repr = False ) emp = employee( "Satyam" , 21 , "ksatyam858" ), emp |
Output:
employee(name='Satyam', age=21, emp_id='ksatyam858')
- hash: If true, this field is included in the generated __hash__() method.
Python3
# hash from dataclasses import dataclass, field # A class for holding an employees content @dataclass (unsafe_hash = True ) class employee: # Attributes Declaration # using Type Hints name: str age: int emp_id: str = field(default_factory = get_emp_id) city: str = field(init = False , default = "patna" , repr = True , hash = True ) emp = employee( "Satyam" , "ksatyam858" , 21 ) hash (emp) |
Output:
28166796391311520
If false then it will not consider these field.
Python3
city: str = field(init = False , default = "patna" , repr = True , hash = False ) # object of the class emp = employee( "Satyam" , "ksatyam858" , 21 ) hash (emp) |
Output:
6124029366977666702
- compare: If true (the default), this field is included in the generated equality and comparison methods (__eq__(), __gt__().
Python3
# hash from dataclasses import dataclass, field # A class for holding an employees content @dataclass (unsafe_hash = True ) class employee: # Attributes Declaration # using Type Hints name: str age: int emp_id: str city: str = field(init = False , default = "patna" , repr = True , hash = False , compare = True ) emp1 = employee( "Satyam" , "ksatyam858" , 21 ) emp2 = employee( "Kumar" , "satyam.10151" , 22 ) emp1 = = emp2 |
Output:
False
- metadata: This can be a mapping or None. None is treated as an empty dict.
Python3
# hash from dataclasses import dataclass, field # A class for holding an employees content @dataclass (unsafe_hash = True ) class employee: # Attributes Declaration # using Type Hints name: str age: int emp_id: str city: str = field(init = False , default = "patna" , repr = True , metadata = { 'format' : 'State' }) emp = employee( "Satyam" , "ksatyam858" , 21 ) emp.__dataclass_fields__[ 'city' ].metadata[ 'format' ] |
Post-init processing
While creating object __post_init__() method call automatically. __init__() code will call a method named __post_init__().
Example: In an employee dataclass, if we want to check employee age, then we can define into the __post_init__() method.
Python3
# A basic Data Class # importing dataclass module from dataclasses import dataclass, field # A class for holding an employees content @dataclass class employee: # Attributes Declaration # using Type Hints name: str emp_id: str age: int city: str # post init function def __post_init__( self ): if self .age > = 30 : self .check_age = True else : self .check_age = False emp = employee( "Satyam" , "ksatyam858" , 21 , 'Patna' ) emp.check_age |
Output:
False
DataClass Inheritance
Inheritance enables us to define a class that takes all the functionality from a parent class.
Example: Child class inherits the properties of the parent class.
Python3
# A basic Data Class # importing dataclass module from dataclasses import dataclass, field # parent class @dataclass class Staff: name: str emp_id: str age: int # child class @dataclass class employee(Staff): salary: int emp = employee( "Satyam" , "ksatyam858" , 21 , 60000 ) emp |
Output:
employee(name='Satyam', emp_id='ksatyam858', age=21, salary=60000)