From the docs:

A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden.

Conversely, this means that any class with no abstract methods or properties like your AbstractClass can be instantiated.


If you want to disallow instantiation of the topmost parent class, you can write a custom class that performs a type check in its __new__ method:

class SubclassOnlyABC(object):
    __metaclass__ = abc.ABCMeta

    def __new__(cls, *args, **kwargs):
        if cls.__bases__ == (SubclassOnlyABC,):
            msg = 'Abstract class {} cannot be instantiated'.format(cls.__name__)
            raise TypeError(msg)

        return super(SubclassOnlyABC, cls).__new__(cls, *args, **kwargs)
class AbstractClass(SubclassOnlyABC):
    pass

class ChildClass(AbstractClass):
    pass

ChildClass()  # works because it's a child class of an abstract class
AbstractClass()  # throws TypeError because its parent class is "object"

You can also write a __new__ method that prevents instantiation of classes with no abstract methods:

class NonEmptyABC(object):
    __metaclass__ = abc.ABCMeta

    def __new__(cls, *args, **kwargs):
        # check if ANY abstractmethod exists
        for parentcls in cls.__mro__:
            if any(getattr(attr, '__isabstractmethod__', False)
                               for attr in vars(parentcls).values()):
                break
        else:
            msg = 'Abstract class {} cannot be instantiated'.format(cls.__name__)
            raise TypeError(msg)

        return super(NonEmptyABC, cls).__new__(cls, *args, **kwargs)
class EmptyAbstractClass(NonEmptyABC):
    pass

class NonemptyAbstractClass(NonEmptyABC):
    @abc.abstractmethod
    def foo(self):
        pass

class NonemptyChild(NonemptyAbstractClass):
    def foo(self):
        pass

NonemptyChild()  # works because "foo" is an abstractmethod
EmptyAbstractClass()  # throws TypeError because there are no abstractmethods
Answer from Aran-Fey on Stack Overflow
🌐
GitHub
github.com › microsoft › pyright › issues › 2547
No errors when using `@abstractmethod` on non-ABC class or when instantiating such class · Issue #2547 · microsoft/pyright
November 6, 2021 - To Reproduce # pyright: strict from abc import abstractmethod class MyAbstract: # does not inherit from ABC @abstractmethod # no error def do_something(self): pass c = MyAbstract().do_something() # also no error Expected behavior An erro...
Author   Tomaz-Vieira
🌐
GitHub
github.com › python › cpython › issues › 100400
You don't need to raise NotImplementedError for abstract methods · Issue #100400 · python/cpython
December 21, 2022 - If "abstract base classes" are meant to mean ABCs from the standard library, this is unnecessary as the ABC metaclass will prohibit instantiation of any derived class that doesn't implement an abstract method.
Author   Xophmeister
🌐
GitHub
github.com › nedbat › coveragepy › issues › 1131
Ignore ABC abstract methods · Issue #1131 · coveragepy/coveragepy
January 18, 2021 - import abc class Foo(abc.ABC): ... with a test. Describe the solution you'd like Coverage should ignore abstract methods by default and should not require coverage for them....
Author   saroad2
Top answer
1 of 5
11

From the docs:

A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden.

Conversely, this means that any class with no abstract methods or properties like your AbstractClass can be instantiated.


If you want to disallow instantiation of the topmost parent class, you can write a custom class that performs a type check in its __new__ method:

class SubclassOnlyABC(object):
    __metaclass__ = abc.ABCMeta

    def __new__(cls, *args, **kwargs):
        if cls.__bases__ == (SubclassOnlyABC,):
            msg = 'Abstract class {} cannot be instantiated'.format(cls.__name__)
            raise TypeError(msg)

        return super(SubclassOnlyABC, cls).__new__(cls, *args, **kwargs)
class AbstractClass(SubclassOnlyABC):
    pass

class ChildClass(AbstractClass):
    pass

ChildClass()  # works because it's a child class of an abstract class
AbstractClass()  # throws TypeError because its parent class is "object"

You can also write a __new__ method that prevents instantiation of classes with no abstract methods:

class NonEmptyABC(object):
    __metaclass__ = abc.ABCMeta

    def __new__(cls, *args, **kwargs):
        # check if ANY abstractmethod exists
        for parentcls in cls.__mro__:
            if any(getattr(attr, '__isabstractmethod__', False)
                               for attr in vars(parentcls).values()):
                break
        else:
            msg = 'Abstract class {} cannot be instantiated'.format(cls.__name__)
            raise TypeError(msg)

        return super(NonEmptyABC, cls).__new__(cls, *args, **kwargs)
class EmptyAbstractClass(NonEmptyABC):
    pass

class NonemptyAbstractClass(NonEmptyABC):
    @abc.abstractmethod
    def foo(self):
        pass

class NonemptyChild(NonemptyAbstractClass):
    def foo(self):
        pass

NonemptyChild()  # works because "foo" is an abstractmethod
EmptyAbstractClass()  # throws TypeError because there are no abstractmethods
2 of 5
10

I usually just declare the base class's __init__ with @abc.abstractmethod. If my base class does not have an __init__, I add a trivial one.

Something like this:

class AbstractClass(abc.ABC):
    @abc.abstractmethod
    def __init__(self):
        pass

    # other useful non-abstract methods...


class ChildClass(AbstractClass):
    def __init__(self):
        pass


if __name__ == '__main__':
    child = ChildClass()  # allowed
    abstract = AbstractClass()  # TypeError
🌐
Reddit
reddit.com › r/learnpython › what's the point of abc & @abstractmethod
r/learnpython on Reddit: What's the point of ABC & @abstractmethod
July 27, 2021 -

Hello. In this first example, I have a short and straightforward code w/ a class for interface. It doesn't inherit from ABC and doesn't have any abstract methods.

class Abs():
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def go_to(self):
        return f"{self.name} is going to {self.place}."
        
class Teacher(Abs):
    place = "work"

class Student(Abs):
    place = "school"
    
t1 = Teacher("James", 56)
s1 = Student("Tim", 15)

print(t1.go_to())
print(s1.go_to())

In this second example, it's the exact opposite.

from abc import ABC, abstractmethod

class Abs(ABC):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    @abstractmethod
    def go_to(self):
        ...
        
class Teacher(Abs):
    place = "work"
    
    def go_to(self):
        return f"{self.name} is going to {self.place}."

class Student(Abs):
    place = "school"
    
    def go_to(self):
        return f"{self.name} is going to {self.place}."
    
t1 = Teacher("James", 56)
s1 = Student("Tim", 15)

print(t1.go_to())
print(s1.go_to())

Both examples have the same output. In the tutorials/articles I've read, most times the second example is preferred. In the abstract class, abstract methods get defined and decorated, and then in the inheriting classes they all get redefined with the rest of the logic. What's the point of creating a class w/ abstract methods which later on we redefine? What issue does that solve? Why not just proceed as in the first example - simple, less code, one parent class for the interface, if we need to add other details, we do so in the base class once and handle the extra logic with that additional info there. Doesn't the first code present a better example of loose coupling - just one connection between parent and child classes, where in the second code, we get connections between parent/child in every method that we redefine? I feel like I'm missing something, because to me, the second example is much more spaghetti-like. If anyone can explain why it's a good practice to redefine abstract methods that would be nice. Also, is it a bad practice to write code as in the first example, w/o ABC+@abstractmethod in the parent class?
Thanks.

Top answer
1 of 5
10
So your examples are a bit problematic because you would never use @abstractmethod in that situation. In your example there is no reason not to define the function only in the parent class--the parent knows everything it needs in order to execute the function, and the children don't change the execution at all. Also, Abs is a terrible name for a class. @abstractmethod is for when you: Require all children to have a method Don't have enough information to define that method in the parent Essentially, it "requires" child classes to define this method. This allows you to include the method in your parent interface so you can document it but raises a sensible error if the child doesn't re-define it. This is mostly useful for parent classes that will never have direct instances--only instances of subclasses. Consider designing a shooter game like Doom or Quake. You might represent various objects and enemies as class instances. To keep the game synced, every clock tick all the objects need to "update" themselves. Enemies might move around, lights might blink, and items might recharge. They all need to do something, but what they do is completely unique to each class. In a case like this, you might define the update() method in the parent Object class. This is mostly a convenience feature--you can write the same code perfectly well without it. However, it allows you to refer to all objects collectively (isinstance(o, Object)) through the parent class, and still ensure that update() exists, even though the parent doesn't know what to do with it. You could easily define update() in the parent and have it do nothing, but this prevents errors from being raised if you call this on a child class that hasn't re-defined the method.
2 of 5
3
let's imagine a List interface - we'll have the operations of append and pop class List(ABC): @abstractmethod def append(self, val): pass @abstractmethod def pop(self): pass now we could create class LinkedList(List) and class ArrayList(List) where we'd implement the methods for both of the list types the reason for using ABC and @abstractmethod is because it doesn't make sense to be able to be able to instantiate a List - that doesn't have an implementation. it only describes what behaviour an implementation should have to provide. think of it as providing a contract by which all users of an object know what behaviour to expect abstract classes and methods are more useful in languages such as java where you can't rely on duck typing void doThing(List list) this would take any subclass of List and be checked at compile time to have the expected methods of append and pop
🌐
Stack Overflow
stackoverflow.com › questions › 46726272 › how-to-create-abstract-classes-using-abc-without-using-an-abstract-method
python - How to create abstract classes using abc without using an abstract method? - Stack Overflow
from abc import ABC, abstractmethod class A(ABC): @abstractmethod def foo(self): print('foo') class B(A): pass obj = B() This will fail because B has not defined the method foo. This mimics the abstract method functionality in Java. I wanted to know if the abstract class functionality is also present in Python, where instantiation of a class is prevented without having any abstract methods.
Top answer
1 of 13
760

Use the abc module to create abstract classes. Use the abstractmethod decorator to declare a method abstract, and declare a class abstract using one of three ways, depending upon your Python version.

In Python 3.4 and above, you can inherit from ABC. In earlier versions of Python, you need to specify your class's metaclass as ABCMeta. Specifying the metaclass has different syntax in Python 3 and Python 2. The three possibilities are shown below:

Copy# Python 3.4+
from abc import ABC, abstractmethod
class Abstract(ABC):
    @abstractmethod
    def foo(self):
        pass
Copy# Python 3.0+
from abc import ABCMeta, abstractmethod
class Abstract(metaclass=ABCMeta):
    @abstractmethod
    def foo(self):
        pass
Copy# Python 2
from abc import ABCMeta, abstractmethod
class Abstract:
    __metaclass__ = ABCMeta

    @abstractmethod
    def foo(self):
        pass

Whichever way you use, you won't be able to instantiate an abstract class that has abstract methods, but will be able to instantiate a subclass that provides concrete definitions of those methods:

>>> Abstract()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Abstract with abstract methods foo
>>> class StillAbstract(Abstract):
...     pass
... 
>>> StillAbstract()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class StillAbstract with abstract methods foo
>>> class Concrete(Abstract):
...     def foo(self):
...         print('Hello, World')
... 
>>> Concrete()
<__main__.Concrete object at 0x7fc935d28898>
2 of 13
152

The old-school (pre-PEP 3119) way to do this is just to raise NotImplementedError in the abstract class when an abstract method is called.

Copyclass Abstract(object):
    def foo(self):
        raise NotImplementedError('subclasses must override foo()!')

class Derived(Abstract):
    def foo(self):
        print 'Hooray!'

>>> d = Derived()
>>> d.foo()
Hooray!
>>> a = Abstract()
>>> a.foo()
Traceback (most recent call last): [...]

This doesn't have the same nice properties as using the abc module does. You can still instantiate the abstract base class itself, and you won't find your mistake until you call the abstract method at runtime.

But if you're dealing with a small set of simple classes, maybe with just a few abstract methods, this approach is a little easier than trying to wade through the abc documentation.

🌐
Justin A. Ellis
jellis18.github.io › post › 2022-01-11-abc-vs-protocol
Abstract Base Classes and Protocols: What Are They? When To Use Them?? Lets Find Out! - Justin A. Ellis
January 11, 2022 - Note that this looks pretty similar to our ABC based Animal class above. We inherit from typing.Protocol instead of abc.ABC and we don't need to add the @abstractmethod decorators since Protocols are not meant to be "implemented" but simply act as an interface in downstream tasks.
Find elsewhere
🌐
GitHub
github.com › python › cpython › blob › main › Lib › abc.py
cpython/Lib/abc.py at main · python/cpython
If cls is not an instance of ABCMeta, does nothing. """ if not hasattr(cls, '__abstractmethods__'): # We check for __abstractmethods__ here because cls might by a C · # implementation or a python implementation (especially ...
Author   python
🌐
PyPI
pypi.org › project › abcmeta
abcmeta · PyPI
What this library provides is apart from that validation it provides validations over the method's signature. All you need is to import ABCMeta and abstractmethod from this library. It works on both annotations and without ...
      » pip install abcmeta
    
Published   Nov 03, 2024
Version   2.2.1
🌐
GitHub
github.com › python › typing › issues › 577
Abstract class methods? · Issue #577 · python/typing
August 1, 2018 - This might not be the right place to put this, but is there any interest in adding a decorator for abstract class methods? (And potentially supporting it in MyPy?) Currently, annotating a method with both @abstractmethod and @classmethod...
Author   sid-kap
🌐
GitHub
github.com › python › typing › discussions › 1487
Annotating `__new__` return type in abstract base class. · python/typing · Discussion #1487
I think that python/mypy#14106 correctly suggests that __new__ with abstract return type should be treated just like a regular method that returns an instance. Beta Was this translation helpful? Give feedback. ... There was an error while loading. Please reload this page. Something went wrong. There was an error while loading. Please reload this page. ... It sounds like you don't want Abc to act like an abstract class, so I'm not sure why you are using ABC as a base class.
Author   python
🌐
Python.org
discuss.python.org › typing
Calling abstract methods - Typing - Discussions on Python.org
January 6, 2024 - PEP 544 indicates that a type checker should generate an error if a class that explicitly derives from the protocol attempts to call a method through super() if that method is unimplemented in the protocol. class Proto(Protocol): def method(self) -> None: ... class Impl(Proto): def method(self) -> None: super().method() # Type checker error This makes sense because the method in the protocol is effectively abstract.
🌐
Python.org
discuss.python.org › python help
AbstractMethods and NotImplementedError - Python Help - Discussions on Python.org
December 22, 2022 - Are there any experts on the use of ABCs and abstractmethod who could weigh in on a documentation issue please? The documentation for the exception says that abstract methods should raise NotImplementedError. Obviously this is not mandatory. Abstract methods can have default implementations.
🌐
Python
docs.python.org › 3 › library › abc.html
abc — Abstract Base Classes
Dynamically adding abstract methods ... supported using the update_abstractmethods() function. The abstractmethod() only affects subclasses derived using regular inheritance; “virtual subclasses” registered with the ABC’s register() ...
🌐
Real Python
realpython.com › ref › glossary › abstract-base-class
abstract base class (ABC) | Python Glossary – Real Python
from abc import ABC, abstractmethod class Animal(ABC): @abstractmethod def speak(self): pass def jump(self): return f"{self.__class__.__name__} is jumping" Animal is an abstract base class with an abstract method .speak() and a regular method .jump(). Subclasses must implement all methods marked with @abstractmethod: ... >>> from animals import Animal >>> class Dog(Animal): ... pass >>> Dog() Traceback (most recent call last): ... TypeError: Can't instantiate abstract class Dog ⮑ without an implementation for abstract method 'speak'
🌐
Learn with Yasir
yasirbhutta.github.io › python › docs › oop-abstraction › abc-class.html
Concept of Abstract Base Classes (ABC) and Abstract Methods | Learn with Yasir
Abstract methods enforce a contract (rules) that all child classes must follow. If a child class fails to implement any abstract method, it remains incomplete and cannot be used. This ensures consistency in the structure of derived classes. The child class must implement all abstract methods ...
🌐
GeeksforGeeks
geeksforgeeks.org › python › abstract-classes-in-python
Abstract Classes in Python - GeeksforGeeks
These properties are declared with the @property decorator and marked as abstract using @abstractmethod. Abstract properties enforce that a subclass provides the property’s implementation. They are especially useful when you want all subclasses to have a certain attribute (like species, category or type). Example: This example defines species as an abstract property, which subclasses must implement. ... from abc import ABC, abstractmethod class Animal(ABC): @property @abstractmethod def species(self): pass class Dog(Animal): @property def species(self): return "Canine" # Instantiate the concrete subclass dog = Dog() print(dog.species)
Published   September 3, 2025