Prevent instantiation of an abstract base class in Python

532 Views Asked by At
  • I have an abstract base class without abstract methods
  • I want to statically check + forbid instantiations of it (with mypy)
from abc import ABC, abstractmethod
from  attrs import frozen

class Abstract(ABC):

    def do_something(self) -> int:
        return 777

    #@abstractmethod
    #def __str__(self) -> str:
    #    ...

@frozen
class Concrete1(Abstract):
    name: str
    some_field: float

@frozen
class Concrete2(Abstract):
    name: int
    some_field: str

a = Abstract()

I can achieve what I want by forcing subclasses to implement an arbitrary method (__str__ here). Is there a better way?

1

There are 1 best solutions below

0
pigrammer On

If your class has no abstract methods, it does not need to be an ABC.

Regarding the part about preventing instantiation, just override __new__():

from  attrs import frozen

class Abstract():

    def do_something(self) -> int:
        return 777
    
    def __new__(cls, *args, **kwargs):
        if cls is Abstract:
            raise TypeError("{cls.__name__} cannot be instantiated, please use a subclass")
        return super().__new__(cls, *args, **kwargs)

@frozen
class Concrete1(Abstract):
    name: str
    some_field: float

@frozen
class Concrete2(Abstract):
    name: int
    some_field: str

a = Abstract() # TypeError: Abstract cannot be instantiated, please use a subclass

Yes, this is not static type checking, but it works.