Abstract classes in Python

Asked

Viewed 512 times

1

The method __subclasscheck__ should be defined at metaclass level, whereas the method __subclasshook__ can be defined as a class method provided that the class has as a metaclass ABC (or one of its derivatives). My question is when we create an abstraction implementing ABCMeta as metaclass, we can make use of the decorator @abstractmethod which states that the method should be overwritten in the derived class, but I have seen in many codes that these methods are used (__subclasscheck__, __subclasshook__) to validate the implementation of methods to be overwritten or to change the behaviour of the method issubclass(). Could someone tell me a use case where one should implement these methods.

1 answer

4


"Provide cases of use" for this type of Feature is quite complicated - it is about functionalities placed in the core of the language to allow advanced class hierarchy handling and customization - the kind of things that will need to be done once, for example, in an ORM, or next to classes-basis of a project with a large hierarchy of classes and very well defined specifics.

Most projects - even large ones, will use frameworks that will already have this type of functionality defined (be it Django, or some other using Sqlalchemy): ie - it’s fine difficult imagine a use case for these features. A concrete and simple use case more difficult yet.

Basically, the __subclasscheck__ in itself, along with the __instancecheck__ are features of the language itself. It would not be false to say that they were introduced in the language precisely to allow the ABC module (Abstract base Classes) to be created with the functionalities it has today.

Basically they allow that by defining a metaclass you can customize and say that some other class, or object of a class unrelated to the classes in your hierarchy (that is, the classes defined with your metaclass), are instances of the same - even though it was never the intention of the person who wrote the original class.

So - to give a concrete example: Python uses Abcmeta to define the classes in Collections.ABC - these yes, can be very useful in everyday life, allowing the user to quickly and easily implement sequences and mappings (even so, it has more use in an intermediate library than in a final project). But basically, when drawing the collections.abc.MutableSequence it would be interesting if someone asked if a list python is a MutableSequence the answer was true: that is, a list has the interface of a Mutablesequence. And that’s why these mechanisms are used in the standard Python library: to say that Python’s native data types - set, frozenset, list, tuple, string, Dict are "subclasses" of the corresponding abstract classes:

In [39]: issubclass(dict, collections.abc.MutableMapping)
Out[39]: True

The same mechanism is used in the class typing stdlib, which is there to provide type-hinting mechanisms for modern code:

In [41]: issubclass(list, typing.MutableSequence)
Out[41]: True

(a Mutablesequence of the Typing module however, exists to indicate that at that point any type that has the interface of a "Changeable Sequence" will be accepted - while Collections.abc.Mutablesequence on the other hand exists to be a base class for user implementations of Mutablesequences by writing as little code as possible. Are different things)

Already - unlike the __subclasscheck__, that goes in metaclass and is a Feature of language, the __subclasshook__ is defined only by the abc module and its Abcmeta metaclass - basically, the __subclasscheck__ of abc.ABCMeta makes the call to __subclashook__. That is - the very mechanism of __subclasshook__ is an example of what can be done with the __subclasscheck__: allow the class itself to have a method for telling whether another class is a subclass of itself (without having to write different code in the metaclass for each class you want to test this kind of thing)

In short:

In 98% of cases you won’t need any of these features. In case you are defining a class hierarchy that makes use of abstract calsses, you can, in the base classes of your hierarchy, use the __subclashook__ to say what will be the response of Python’s built-in calls issubclass and isinstance for objects (and classes) outside their hierarchy. (or crossing branches of their hierarchy). These are the remaining "2%".

In the standard library this mechanism is used to say that native types like Dict, list, etc...are subclasses of "Mutablemapping", "Mutablesequence"... as appropriate.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.