How to create an abstract attribute for an abstract class in Python?

Viewed 115

I already found some similar question where they try to create abstract attributes and they all suggest using @property and @abc.abstractmethod to achieve that like here. There are many similar topics but I cant find a way to do it without using the @property decorator. The reason that I don't want to use it is because I don't want to create setter and getter methods in my concrete classes. I simply want to enforce that my concrete classes will have a specific attribute for example self.filter_name which holds an encrypted version of the class's name.

This is my abstract class at the moment with the @property and @abc.abstractmethod decorators:

import abc
from typing import List

class DataFilter:
    @property
    @abc.abstractmethod
    def filter_name(self)-> str:
        """Returns the filter name encrypted"""
        pass

If I do the above and simply try to set my self.filter_name attribute in my concrete class to a specific value I get an AttributeError: can't set attribute. I wish to only have something like self.filter_name = "blabla" in my concrete class.

1 Answers

The way to enforce this is not with abstractmethod, but via __init_subclass__.

class DataFilter:
    def __init_subclass__(cls, **kwargs):
       super().__init_subclass__(**kwargs)
       try:
           cls.filter_name
       except AttributeError:
           raise TypeError("Can't instantiate class DataFilter without name 'filter_name'")
    

You can perform additional tests on the value of cls.filter_name if it is present.

Related