@Oddthinking's answer is not wrong, but I think it misses the real, practical reason Python has ABCs in a world of duck-typing.

Abstract methods are neat, but in my opinion they don't really fill any use-cases not already covered by duck typing. Abstract base classes' real power lies in the way they allow you to customise the behaviour of isinstance and issubclass. (__subclasshook__ is basically a friendlier API on top of Python's __instancecheck__ and __subclasscheck__ hooks.) Adapting built-in constructs to work on custom types is very much part of Python's philosophy.

Python's source code is exemplary. Here is how collections.Container is defined in the standard library (at time of writing):

class Container(metaclass=ABCMeta):
    __slots__ = ()

    @abstractmethod
    def __contains__(self, x):
        return False

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Container:
            if any("__contains__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

This definition of __subclasshook__ says that any class with a __contains__ attribute is considered to be a subclass of Container, even if it doesn't subclass it directly. So I can write this:

class ContainAllTheThings(object):
    def __contains__(self, item):
        return True

>>> issubclass(ContainAllTheThings, collections.Container)
True
>>> isinstance(ContainAllTheThings(), collections.Container)
True

In other words, if you implement the right interface, you're a subclass! ABCs provide a formal way to define interfaces in Python, while staying true to the spirit of duck-typing. Besides, this works in a way that honours the Open-Closed Principle.

Python's object model looks superficially similar to that of a more "traditional" OO system (by which I mean Java*) - we got yer classes, yer objects, yer methods - but when you scratch the surface you'll find something far richer and more flexible. Likewise, Python's notion of abstract base classes may be recognisable to a Java developer, but in practice they are intended for a very different purpose.

I sometimes find myself writing polymorphic functions that can act on a single item or a collection of items, and I find isinstance(x, collections.Iterable) to be much more readable than hasattr(x, '__iter__') or an equivalent try...except block. (If you didn't know Python, which of those three would make the intention of the code clearest?)

That said, I find that I rarely need to write my own ABC and I typically discover the need for one through refactoring. If I see a polymorphic function making a lot of attribute checks, or lots of functions making the same attribute checks, that smell suggests the existence of an ABC waiting to be extracted.

*without getting into the debate over whether Java is a "traditional" OO system...


Addendum: Even though an abstract base class can override the behaviour of isinstance and issubclass, it still doesn't enter the MRO of the virtual subclass. This is a potential pitfall for clients: not every object for which isinstance(x, MyABC) == True has the methods defined on MyABC.

class MyABC(metaclass=abc.ABCMeta):
    def abc_method(self):
        pass
    @classmethod
    def __subclasshook__(cls, C):
        return True

class C(object):
    pass

# typical client code
c = C()
if isinstance(c, MyABC):  # will be true
    c.abc_method()  # raises AttributeError

Unfortunately this one of those "just don't do that" traps (of which Python has relatively few!): avoid defining ABCs with both a __subclasshook__ and non-abstract methods. Moreover, you should make your definition of __subclasshook__ consistent with the set of abstract methods your ABC defines.

Answer from Benjamin Hodgson on Stack Overflow
🌐
Python
docs.python.org › 3 › library › abc.html
abc — Abstract Base Classes
The abstractmethod() only affects subclasses derived using regular inheritance; “virtual subclasses” registered with the ABC’s register() method are not affected. When abstractmethod() is applied in combination with other method descriptors, it should be applied as the innermost decorator, as shown in the following usage examples:
🌐
The Teclado Blog
blog.teclado.com › python-abc-abstract-base-classes
How to Write Cleaner Python Code Using Abstract Classes
October 26, 2022 - The abc module comes with a metaclass ABCMeta. back in the days we had to use it to define metaclasses with metaclass=abc.ABCMeta. Nowadays, just inheriting from ABC does the same thing—so you don't have to worry about metaclasses at all! In this blog post we described the basics of Python's abstract classes.
🌐
DataCamp
datacamp.com › tutorial › python-abstract-classes
Python Abstract Classes: A Comprehensive Guide with Examples | DataCamp
January 22, 2025 - Learn about Python abstract classes, their purpose, and how to use the `abc` module to enforce consistent interfaces. Includes practical examples and best practices for effective implementation.
Top answer
1 of 6
351

@Oddthinking's answer is not wrong, but I think it misses the real, practical reason Python has ABCs in a world of duck-typing.

Abstract methods are neat, but in my opinion they don't really fill any use-cases not already covered by duck typing. Abstract base classes' real power lies in the way they allow you to customise the behaviour of isinstance and issubclass. (__subclasshook__ is basically a friendlier API on top of Python's __instancecheck__ and __subclasscheck__ hooks.) Adapting built-in constructs to work on custom types is very much part of Python's philosophy.

Python's source code is exemplary. Here is how collections.Container is defined in the standard library (at time of writing):

class Container(metaclass=ABCMeta):
    __slots__ = ()

    @abstractmethod
    def __contains__(self, x):
        return False

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Container:
            if any("__contains__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

This definition of __subclasshook__ says that any class with a __contains__ attribute is considered to be a subclass of Container, even if it doesn't subclass it directly. So I can write this:

class ContainAllTheThings(object):
    def __contains__(self, item):
        return True

>>> issubclass(ContainAllTheThings, collections.Container)
True
>>> isinstance(ContainAllTheThings(), collections.Container)
True

In other words, if you implement the right interface, you're a subclass! ABCs provide a formal way to define interfaces in Python, while staying true to the spirit of duck-typing. Besides, this works in a way that honours the Open-Closed Principle.

Python's object model looks superficially similar to that of a more "traditional" OO system (by which I mean Java*) - we got yer classes, yer objects, yer methods - but when you scratch the surface you'll find something far richer and more flexible. Likewise, Python's notion of abstract base classes may be recognisable to a Java developer, but in practice they are intended for a very different purpose.

I sometimes find myself writing polymorphic functions that can act on a single item or a collection of items, and I find isinstance(x, collections.Iterable) to be much more readable than hasattr(x, '__iter__') or an equivalent try...except block. (If you didn't know Python, which of those three would make the intention of the code clearest?)

That said, I find that I rarely need to write my own ABC and I typically discover the need for one through refactoring. If I see a polymorphic function making a lot of attribute checks, or lots of functions making the same attribute checks, that smell suggests the existence of an ABC waiting to be extracted.

*without getting into the debate over whether Java is a "traditional" OO system...


Addendum: Even though an abstract base class can override the behaviour of isinstance and issubclass, it still doesn't enter the MRO of the virtual subclass. This is a potential pitfall for clients: not every object for which isinstance(x, MyABC) == True has the methods defined on MyABC.

class MyABC(metaclass=abc.ABCMeta):
    def abc_method(self):
        pass
    @classmethod
    def __subclasshook__(cls, C):
        return True

class C(object):
    pass

# typical client code
c = C()
if isinstance(c, MyABC):  # will be true
    c.abc_method()  # raises AttributeError

Unfortunately this one of those "just don't do that" traps (of which Python has relatively few!): avoid defining ABCs with both a __subclasshook__ and non-abstract methods. Moreover, you should make your definition of __subclasshook__ consistent with the set of abstract methods your ABC defines.

2 of 6
214

Short version

ABCs offer a higher level of semantic contract between clients and the implemented classes.

Long version

There is a contract between a class and its callers. The class promises to do certain things and have certain properties.

There are different levels to the contract.

At a very low level, the contract might include the name of a method or its number of parameters.

In a staticly-typed language, that contract would actually be enforced by the compiler. In Python, you can use EAFP or type introspection to confirm that the unknown object meets this expected contract.

But there are also higher-level, semantic promises in the contract.

For example, if there is a __str__() method, it is expected to return a string representation of the object. It could delete all contents of the object, commit the transaction and spit a blank page out of the printer... but there is a common understanding of what it should do, described in the Python manual.

That's a special case, where the semantic contract is described in the manual. What should the print() method do? Should it write the object to a printer or a line to the screen, or something else? It depends - you need to read the comments to understand the full contract here. A piece of client code that simply checks that the print() method exists has confirmed part of the contract - that a method call can be made, but not that there is agreement on the higher level semantics of the call.

Defining an Abstract Base Class (ABC) is a way of producing a contract between the class implementers and the callers. It isn't just a list of method names, but a shared understanding of what those methods should do. If you inherit from this ABC, you are promising to follow all the rules described in the comments, including the semantics of the print() method.

Python's duck-typing has many advantages in flexibility over static-typing, but it doesn't solve all the problems. ABCs offer an intermediate solution between the free-form of Python and the bondage-and-discipline of a staticly-typed language.

🌐
Python Course
python-course.eu › oop › the-abc-of-abstract-base-classes.php
20. The 'ABC' of Abstract Base Classes | OOP | python-course.eu
from abc import ABC, abstractmethod class AbstractClassExample(ABC): @abstractmethod def do_something(self): print("Some implementation!") class AnotherSubclass(AbstractClassExample): def do_something(self): super().do_something() print("The enrichment from AnotherSubclass") x = AnotherSubclass() x.do_something() Some implementation! The enrichment from AnotherSubclass ... Enjoying this page? We offer live Python training courses covering the content of this site.
🌐
Python
docs.python.org › 3 › library › collections.abc.html
collections.abc — Abstract Base Classes for Containers
Several of the ABCs are also useful ... For example, to write a class supporting the full Set API, it is only necessary to supply the three underlying abstract methods: __contains__(), __iter__(), and __len__()....
🌐
W3Schools
w3schools.com › python › ref_module_abc.asp
Python abc Module
Python Examples Python Compiler Python Exercises Python Quiz Python Challenges Python Server Python Syllabus Python Study Plan Python Interview Q&A Python Bootcamp Python Certificate Python Training ... from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def area(self): pass class Square(Shape): def __init__(self, s): self.s = s def area(self): return self.s * self.s sq = Square(3) print(isinstance(sq, Shape)) print(sq.area()) Try it Yourself »
🌐
Earthly
earthly.dev › blog › abstract-base-classes-python
Abstract Base Classes in Python - Earthly Blog
July 19, 2023 - Another difference even though it is not clear in Python due to the lack of native support of interfaces is that you implement an interface and inherit an ABC, to expound on this is that other languages have keywords like implements and extends that clearly indicate the action you are taking in child class in relation to a parent class. Here is an example of an interface for a shape that requires implementing classes to have methods for calculating area and perimeter.
Find elsewhere
🌐
Python Module of the Week
pymotw.com › 2 › abc
abc – Abstract Base Classes - Python Module of the Week
$ python abc_abstractproperty_rw_deco.py Implementation.value: Default value Changed value: New value · The collections module defines several abstract base classes related to container (and containable) types. ... In addition to serving as detailed real-world examples of abstract base classes, Python’s built-in types are automatically registered to these classes when you import collections.
🌐
Real Python
realpython.com › ref › glossary › abstract-base-class
abstract base class (ABC) | Python Glossary – Real Python
To define an abstract base class, you inherit from abc.ABC and use the @abstractmethod decorator to mark methods that must be implemented by subclasses. Attempting to instantiate an abstract base class or a subclass that hasn’t implemented all abstract methods will raise a TypeError exception. Here’s an example of how to define and use an abstract base class in Python...
🌐
Python
peps.python.org › pep-3119
PEP 3119 – Introducing Abstract Base Classes | peps.python.org
Another example would be someone who wants to define a generic function (PEP 3124) for any sequence that has an append() method. The Sequence ABC (see below) doesn’t promise the append() method, while MutableSequence requires not only append() but also various other mutating methods.
🌐
GeeksforGeeks
geeksforgeeks.org › abstract-base-class-abc-in-python
Abstract Base Class (abc) in Python - GeeksforGeeks
August 29, 2020 - The main purpose of using Abstract ... ABCs and Alternative-Collection ABCs. ... Python has five abstract base classes. They are as follows: ... These abstract base classes contain one abstract method each. Let's consider an example of the __len__ method....
🌐
GeeksforGeeks
geeksforgeeks.org › python › abstract-classes-in-python
Abstract Classes in Python - GeeksforGeeks
Example: This example shows the error raised when trying to instantiate an abstract class. ... from abc import ABC, abstractmethod class Animal(ABC): @abstractmethod def make_sound(self): pass # animal = Animal() # TypeError: Can't instantiate ...
Published   September 3, 2025
🌐
Geek Python
geekpython.in › abc-in-python
Python's ABC: Understanding the Basics of Abstract Base Classes
October 29, 2023 - Python will raise an error upon executing the above code because the class Sachin doesn’t follow the class Details blueprint. As we saw in the above example that if a derived class doesn’t follow the blueprint of the abstract class, then the error will be raised. That’s where ABC(Abstract Base Class) plays an important role in making sure that the subclasses must follow that blueprint.
🌐
YouTube
youtube.com › watch
Python Interfaces and Abstract Base Class (ABC): A Must-Know for Advanced Programmers - YouTube
Take your Python programming skills to the next level with this must-know topic: interfaces and abstract classes. Learn how to implement these important conc...
Published   February 22, 2024
🌐
Reddit
reddit.com › r/learnpython › understanding abc.abc
r/learnpython on Reddit: Understanding abc.ABC
June 20, 2023 -

I am being asked to maintain code that subclasses from abc.ABC. I have read the python documentation, the associated PEP, and even visited pymotw. I do not understand what abstract classes give you.

If I have class A and then I derive subclass B from it wouldn't issubclass(B,A) still be true?

Top answer
1 of 4
4
If I have class A and then I derive subclass B from it wouldn't issubclass(B,A) still be true? Usually, yes, unless you do something weird with metaclasses maybe. I do not understand what abstract classes give you. You can think of them as some kind of "contracts"; any class inheriting from them implicitly makes a promise to support the interface defined by the abstract base class. It's not nearly as binding or robust as something like Rust's trait system, but it can still come in handy sometimes. For example, os.PathLike is an abstract base class that defines a common interface all path-like objects, such as pathlib.Path, must fulfill to be compatible with most standard library functions expecting filepaths as arguments. The subclasses can add more functionality on top of the required methods, but they are forced to at least have the ones set by the abstract base class. In other words, you can always count on those being available no matter what kind of subclass you're getting.
2 of 4
4
Abstract base classes are just classes that aren't meant to be instantiated. It is like a wireframe for shared methods / attributes, without the ABC itself being a legitimate object type. It works the same as regular subclassing in most ways. ABCs usually have the shared methods defined so that if you make a subclass of it and it doesn't implement something the interface was expected to it will throw an error. class PersonNormal: def __init__(self, name: str): self.name = name def say_hi(self): print(f"Hi, I'm {self.name}") class PersonABC(ABC): def __init__(self, name): ... @abstractmethod def say_hi(self): ... class Student(Person): def __init__(self, name: str): super().__init__(name) class Teacher(Person) def __init__(self, name: str): super().__init__(name) def say_hi(self): print(f"Good morning, I'm Mr. {self.name}") # inheriting from PersonNormal A = Person('John') B = Student('Peter') C = Teacher('Tom') A.say_hi() # calls Person.say_hi normally B.say_hi() # calls Person.say_hi since it wasn't overwritten C.say_hi() # calls Teacher.say_hi # inheriting from PersonABC A = Person('John') # TypeError can't instantiate abstract class Person... B = Student('Peter') # TypeError since you didn't overwrite the method C = Teacher('Tom') # works as expected
🌐
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
🌐
Medium
medium.com › analytics-vidhya › abc-in-python-abstract-base-class-35808a9d6b32
ABC in Python (Abstract Base Class) | by nijanthan | Analytics Vidhya | Medium
March 12, 2024 - Dynamically adding abstract methods to a class, or attempting to modify the abstraction status of a method or class once it is created, are not supported. The abstractmethod() only affects subclasses derived using regular inheritance; “virtual subclasses” registered with the ABC’s register() method are not affected.
🌐
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 - Protocols were introduced in PEP-544 as a way to formally incorporate structural subtyping (or "duck" typing) into the python type annotation system. There are two main, but related, use cases for Protocols. First, they can be used as an interface for classes and functions which can be used downstream in other classes or functions. Secondly, they can be used to set bounds on generic types. Protocols allow you to define an interface for a class or function that will be type checked on usage rather than on creation. For example, we can make our Animal ABC above a Protocol