Skip to content Skip to sidebar Skip to footer

Strange Behaviour When Mixing Abstractmethod, Classmethod And Property Decorators

I've been trying to see whether one can create an abstract class property by mixing the three decorators (in Python 3.9.6, if that matters), and I noticed some strange behaviour. C

Solution 1:

This looks like a bug in the logic that checks for inherited abstract methods.

An object in a class dict is considered abstract if retrieving its __isabstractmethod__ attribute produces True. When Bar subclasses Foo, Python needs to determine whether Bar overrides the abstract Foo.x, and if so, whether the override is itself abstract. It should do this by searching the MRO for an 'x' entry in a class dict, so it can examine __isabstractmethod__ on descriptors directly without invoking the descriptor protocol, but instead, it performs a simple Bar.x attribute access.

The Bar.x attribute access invokes the class property. It also returns None instead of the abstract property, and None isn't abstract, so Python gets confused about whether Bar.x is abstract. Python ends up still thinking Bar.x is abstract due to a different check, but if you change the example a bit:

>>>from abc import ABC, abstractmethod>>>>>>classFoo(ABC):...    @classmethod...    @property...    @abstractmethod...defx(cls):...print(cls)...returnNone...>>>classBar(Foo): pass... 
<class '__main__.Bar'>
>>>Bar()
<__main__.Bar object at 0x7f46eca8ab80>

Python ends up thinking Bar is a concrete class, even though the changed example doesn't override x at all.

Solution 2:

You can try raising an exception in Bar.x. This way you can see where it is called.

It should lead you to abc.py in the standard library, specifically the line _abc_init(cls). This function is implemented in C. One of the first things this does is call compute_abstract_methods(self) checks all the abstract methods the class has inherited to see if they're implemented. This means getting Bar.x which invokes the property getter.

Post a Comment for "Strange Behaviour When Mixing Abstractmethod, Classmethod And Property Decorators"