Why Use Abstract Base Classes in Python

Why use Abstract Base Classes in Python?

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.

When and Why to use abstract classes/methods?

I know the basic use of abstract classes
is to create templates for future
classes. But are there any more uses
of them?

Not only can you define a template for children, but Abstract Classes offer the added benefit of letting you define the functionality that your child classes can utilize later.

You could not provide a default method implementation in an Interface prior to Java 8.

When should you prefer them over
interfaces and when not?

Abstract Classes are a good fit if you want to provide implementation details to your children but don't want to allow an instance of your class to be directly instantiated (which allows you to partially define a class).

If you want to simply define a contract for Objects to follow, then use an Interface.

Also when are abstract methods useful?

Abstract methods are useful in the same way that defining methods in an interface is useful. It's a way for the designer of the Abstract class to say "any child of mine MUST implement this method".

Is it a good practice to put common methods to an abstract class in Python?

TL; DR; Yes, it is OK for an abstract class to have non-abstract methods.

Typically what we call an abstract class is just a class that cannot be instantiated.

On the other hand what we call an interface is a class which has only method declarations but no implementations. In particular its an abstract class because it doesn't have a constructor.

Of course in Python there are no real interfaces: every method has to have a body. But we can somewhat emulate interfaces via raise NotImplementedError().

Anyway interfaces form a subset of abstract classes. This obviously suggests that there are abstract classes that are not interfaces. This is exactly the case you are describing. Yes, abstract class may contain implemented, non-abstract methods. And it is not a bad practice. This is especially useful when a given method does not depend on concrete implementation.


For example consider an interface for a generic parser (I'm thinking about json.load and json.loads):

class ILoader(ABC):
@abstractmethod
def load(self, stream):
raise NotImplementedError()

It's completely OK to give loads method which accepts a string instead of stream with a default implementation:

class AbstractLoader(ABC):
@abstractmethod
def load(self, stream):
raise NotImplementedError()

def loads(self, text):
stream = io.StringIO(text)
return self.load(stream)

although I would use Abstract prefix instead of I. ;)

Why are abstract classes that do nothing used?

why ABC and abstract method is used?

In OOP, it's called interface. It defines the function prototype that inherited class need to implement. In your example, those ConcreteStrategyA and ConcreteStrategyB are concrete classes that inherited from the Strategy interface.

why is an empty Strategy class used?

It's not empty. It defines the interface that derived classes are inherited from.

Understanding Abstract Base Classes in Python

Your code demonstrates that the second statement is true. It doesn't show that the first statement is false.

In your code, you are trying to instantiate AnotherSubclass, which is not allowed because AnotherSubclass does not implement all the abstract methods. The second statement says this.

However, if you delete the last two lines, i.e. not instantiating AnotherSubclass, then your code will produce no errors when you try to run it. This shows that the first statement is true - subclasses of abstract classes that doesn't implement all its abstract methods are allowed to exist.

You can write another subclass of AnotherSubclass called YetAnotherClass, this time implementing the abstract method, and you will be able to instantiate YetAnotherClass. Note that your program now does something, and AnotherSubclass is still allowed to exist.



Related Topics



Leave a reply



Submit