Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mark a class as abstract without defining any abstract methods

Tags:

python

I'm looking for something like this:

from abc import ABC

@abstractclass
class A(ABC):
    pass

A()  # FAILS

class B(A):
    pass

B()  # SUCCEEDS

I'm aware of the option of decorating the c'tor or some dummy method in A with abstractmethod, but this requires me to override it in B. This is exactly what I'm trying to avoid.

like image 929
Hetzroni Avatar asked Feb 27 '18 16:02

Hetzroni


Video Answer


1 Answers

You can customize __new__:

from abc import ABC, abstractmethod

class A(ABC):
    def __new__(cls):
        if cls is A:
            raise TypeError("Can't instantiate abstract class {}".format(A.__name__))
        return super(A, cls).__new__(cls)

class B(A):
    pass

A()  # TypeError
B()  # Ok

You can also make it decorator-style, for example like this (works as long as the decorated class didn't customize __new__):

def abstractclass(decorated_cls):
    def clsnew(cls):
        if cls is decorated_cls:
            raise TypeError("Can't instantiate abstract class {}".format(decorated_cls.__name__))
        return super(decorated_cls, cls).__new__(cls)
    decorated_cls.__new__ = clsnew
    return decorated_cls

@abstractclass
class A(ABC):
    pass

class B(A):
    pass

A()  # TypeError
B()  # Ok
like image 163
jdehesa Avatar answered Nov 15 '22 07:11

jdehesa