Industrial manufacturing
Industrial Internet of Things | Industrial materials | Equipment Maintenance and Repair | Industrial programming |
home  MfgRobots >> Industrial manufacturing >  >> Industrial programming >> Python

Master Python Attrs: Build Advanced Data Classes with Practical Examples

Master Python Attrs: Build Advanced Data Classes with Practical Examples

The package Python Attrs allows you to create advanced data classes using simple annotations. Of course, python has its own native data class module as well, but the Python attrs package offers a couple of extra features you might like!

Table of contents

Install attrs

The attrs package is not part of the base library, so you will need to install it with the pip install command or something similar, like Pipenv. You probably also want to create a virtual environment, so it won’t interfere with other projects you have. The package is called attrs, so installing it will look like this:

$ pip install attrs

# or with pipenv:
$ pipenv install attrs

Attrs vs data classes

The authors of attrs have, in fact, worked on the PEP that introduced data classes into Python. Python’s native data classes are intentionally kept simpler and easier to understand while attrs offering the full range of features you might want!

Some of the reasons to choose Python attrs over the built-in data classes are:

A basic Python attrs example

Let’s look at a very basic example first:

import attr

@attr.s
class Person(object):
    name = attr.ib(default='John')
    surname = attr.ib(default='Doe')
    age = attr.ib(init=False)
    
p = Person()
print(p)
p = Person('Bill', 'Gates')
p.age = 60
print(p)

# Output: 
#   Person(name='John', surname='Doe', age=NOTHING)
#   Person(name='Bill', surname='Gates', age=60)

A couple of observations:

Next let’s look at the most important features this package offers over regular data classes: validators and converters.

Python attrs validator example

You can add validators to you attrs data class in two ways:

  1. Using a decorator
  2. By providing a callable function

I’ll demonstrate the callable function method here first. Attrs offers several validators out of the box, of which we’ll use the instance_of validator in the following example:

>>> @attr.s
... class C(object):
...     x = attr.ib(validator=attr.validators.instance_of(int))
>>> C(42)
C(x=42)
>>> C("a string")

Traceback (most recent call last):
   ...
TypeError: ("'x' must be <type 'int'> (got 'a string' that is a <type 'str'>).", ...

Since we tried to create an object C with a string value for x, the instance_of validator throws an error because it requires an int type instead of a string.

Let’s now define our own validator:

import attr

@attr.s
class DividableByTwo(object):
    x = attr.ib()

    @x.validator
    def check(self, attribute, value):
        if value % 2 != 0:
            raise ValueError(f'{value} is not dividable by 2')

print (DividableByTwo(60))
print (DividableByTwo(11))

# Output will be something like:
# DividableByTwo(x=60)
# ...
# ValueError: 11 is not dividable by 2

Python attrs converter example

A converter takes the value that is set and converts it automatically. You can use this for all kinds of purposes. One example is to automatically convert a value to an int. Again, let’s start with using a callable function, in this case we simply use Python’s int() function:

import attr

@attr.s
class C(object):
    x = attr.ib(converter=int)

c = C("1")
print(c)
# Output:
# C(x=1)

Our input (the string “1”) was converted to an integer automatically. Because converters are run before validators, you can validate the final value after conversion. E.g., you could come the above two examples to first convert any input to int, and then check if the value is dividable by two.

Using slots with Python attrs

Finally, you can tell attrs to use slotted classes. Slotted classes have some advantages over regular classes:

In short, with a slotted class you explicitly state which instance attributes you expect your object instances to have. This way, Python can leave out some checks and such, resulting in less memory usage and slight speed increases. You can find more details in the attrs documentation here.

However, slotted classes come with caveats too, especially when you manually create them. Luckily, attrs offers us a simple way to enable the feature:

import attr

@attr.s(slots=True)
class YourClassName:
    ...

Keep learning


Python

  1. Mastering Python Data Types: A Practical Guide
  2. Encapsulation in Java: A Comprehensive Guide with Practical Example
  3. Python OOP Fundamentals: Classes, Objects, Inheritance, and Constructors Explained
  4. Mastering Python’s strip() Method: Comprehensive Guide & Practical Examples
  5. Python Counter in collections – Efficient Counting, Updating, and Arithmetic Operations
  6. Creating ZIP Archives in Python: From Full Directory to Custom File Selection
  7. Python List index() – How to Find Element Positions with Practical Examples
  8. Master Python Regular Expressions: re.match(), re.search(), re.findall() – Practical Examples
  9. Python Calendar Module: Expert Guide with Code Examples
  10. Master Python Multithreading: GIL Explained with Practical Examples