Provide a canonical way to declare an abstract class variable

That’s a fair point. I think it’s because there are generally far less class attributes/variables defined than there are instance attibutes/variables in any given real-world project, and among the class attributes defined only a small fraction of them are conceptually abstract. And even when there are class variables that should justifiably be made abstract, developers can shrug off the lack of this language feature by simply declaring them as normal class variables as @ncoghlan suggested, and let the downstream classes pick up the errors if these class variables are not overridden and are accessed at runtime. As a result developers of major programming languages so far have ignored this relatively occasional need.

Aside from the aforementioned lib2to3 package, a few other places in CPython’s standard library that could/could’ve benefitted from abstract class variable declarations include:

asyncio.events.BaseDefaultEventLoopPolicy._loop_factory:

logging.handlers.BaseRotatingHandler.rotator:

pathlib._Flavour.sep and friends, although these have now been refactored to use their equivalents in the os module:

importlib._bootstrap.BuiltinImporter._ORIGIN, where BuiltinImporter and FrozenImporter should be made to inherit from an abstract base class with all the common abstract methods and the abstract class variable _ORIGIN:

But yeah, these examples are admittedly small in number, probably too small to be worth the effort.

1 Like

If I could weigh in here, I have only just now discovered this thread and this EXACT thing (and/or lack of it) has lost me multiple days of work because I have been trying to type-annotate existing code. And, because of the peculiarities of needing an abstract class attribute and not being able to make one.

What I ended up doing was making (by accident, before I learned more about the differences) a weird mish-mash of an abstract instance property in the abstract base class and a class attribute in the concrete derived classes. It actually works fine in run-time but wreaks havoc when trying to type-hint my code. My run-time checking is already fine, but what I wanted was type-checkers to find it ahead of time like using @abstractmethod does.

What I ended up doing to enable complete type annotations was just abandoning the abstract nature entirely and turning what was an instance property in the base class into a true class attribute - it still runs fine (and fails fine) since I have custom registration stuff that catches any issues in run-time, but I still wish I could make the type-checker find it. So … is the desire for something like this widespread? I have no idea. Are there people out there who would really really like this? Yes! raises hand :smile:

2 Likes

Although this approach of abusing an abstract property as an abstract variable works

No it does not work, the goal of class variable is to be able to use Class.variable, not instance.variable, since you often have no instance at all when you want to use a class variable.