Search code examples
pythonabstract-classclass-methodabstract-methods

Python 3.6: abc.abstracmethod on classmethod no check on class level call


With python 3.6, When I decorate an abstractmehod with abc.abstractmethod withing a class having metaclass=abc.ABCMeta, the abstract method can be called from a class (not instance) point of view.

It seems that the abc decorators are performing the checks when the class is instanciated, so it is not done when calling from instance.

This behavior is highly disturbing and it looks like a bug in the abc module.

What did I miss?

Thanks

Code example:

import abc
import sys

class P(metaclass=abc.ABCMeta):
    @classmethod
    @abc.abstractmethod
    def acm(cls):
        pass

class X(P):
    pass

print("P.acm()", file=sys.stderr)
try:
    P.acm()
    print("OK")
except Exception as e:
    print(f"KO: {e}")

print("P().acm()", file=sys.stderr)
try:
    P().acm()
    print("OK")
except Exception as e:
    print(f"KO: {e}")

Results:

P.acm()
OK
P().acm()
KO: Can't instantiate abstract class P with abstract methods acm

Solution

  • This behavior is consistent with the behavior described in the documentation for @classmethod.

    https://docs.python.org/3.6/library/functions.html?highlight=classmethod#classmethod

    "It can be called either on the class (such as C.f()) or on an instance (such as C().f())."

    In this case, it can't be called on an instance because it is abstract, but since it's a classmethod, it is still okay to call it on the class directly.