Related Articles

Related Articles

Understanding Python Dataclasses
  • Last Updated : 01 Oct, 2020

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

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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 funtion 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 funtion 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)))
  
  
# initlization 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()
  
# refering 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)

chevron_right


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 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

filter_none

edit
close

play_arrow

link
brightness_4
code

# A basic Data Class
# importing dataclass module
from dataclasses import dataclass
  
# A class for holding an employess 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()
  
# refering 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)

chevron_right


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

filter_none

edit
close

play_arrow

link
brightness_4
code

from dataclasses import dataclass
  
# A class for holding an employess 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__

chevron_right


Output:

Explanation of the parameters :



  • default: This field is used to specify default values for this field.

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# default field example
from dataclasses import dataclass, field
  
  
# A class for holding an employess 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)

chevron_right


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

filter_none

edit
close

play_arrow

link
brightness_4
code

# default factory example
from dataclasses import dataclass, field
  
  
def get_emp_id():
    id = 2345
    return id
  
# A class for holding an employess 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)

chevron_right


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

filter_none

edit
close

play_arrow

link
brightness_4
code

# init field example
from dataclasses import dataclass, field
  
# A class for holding an employess 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)

chevron_right


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

filter_none

edit
close

play_arrow

link
brightness_4
code

# repr field
from dataclasses import dataclass, field
  
# A class for holding an employess 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)

chevron_right


Output:

employee(name=’Satyam’, age=21, emp_id=’ksatyam858′, city=’patna’)

If repr is false then:

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

city: str = field(init=False, default="patna", repr=False)
  
emp = employee("Satyam", 21, "ksatyam858"),
emp

chevron_right


Output:

employee(name='Satyam', age=21, emp_id='ksatyam858')
  • hash: If true, this field is included in the generated __hash__() method.

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# hash
from dataclasses import dataclass, field
  
# A class for holding an employess 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)

chevron_right


Output:

28166796391311520

If false then it will not consider these field.

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

city: str = field(init=False, default="patna", repr=True, hash=False)
  
# object of the class
emp = employee("Satyam", "ksatyam858", 21)
hash(emp)

chevron_right


Output:

6124029366977666702
  • compare: If true (the default), this field is included in the generated equality and comparison methods (__eq__(), __gt__().

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# hash
from dataclasses import dataclass, field
  
# A class for holding an employess 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

chevron_right


Output:

False
  • metadata: This can be a mapping or None. None is treated as an empty dict.

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# hash
from dataclasses import dataclass, field
  
# A class for holding an employess 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']

chevron_right


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

filter_none

edit
close

play_arrow

link
brightness_4
code

# A basic Data Class
# importing dataclass module
from dataclasses import dataclass, field
  
  
# A class for holding an employess 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

chevron_right


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

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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

chevron_right


Output:

employee(name='Satyam', emp_id='ksatyam858', age=21, salary=60000)

Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.

To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course.

My Personal Notes arrow_drop_up
Recommended Articles
Page :