Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Oppiskele Defining ABCs with the abc Module | The Foundations of ABCs
Python Abstract Base Classes

Defining ABCs with the abc Module

Pyyhkäise näyttääksesi valikon

Python's abc module provides two ways to define an abstract base class: inheriting from ABC or using ABCMeta as a metaclass directly. Both achieve the same result – the choice is mostly stylistic.

Inheriting from ABC

The simplest approach is to inherit from abc.ABC. This automatically sets ABCMeta as the metaclass:

1234567891011121314151617181920212223
from abc import ABC, abstractmethod # Defining an ABC by inheriting from ABC class PaymentProcessor(ABC): @abstractmethod def process(self, amount): pass @abstractmethod def refund(self, transaction_id): pass # Concrete implementation class StripeProcessor(PaymentProcessor): def process(self, amount): return f"Stripe: processing ${amount:.2f}" def refund(self, transaction_id): return f"Stripe: refunding {transaction_id}" processor = StripeProcessor() print(processor.process(99.99)) print(processor.refund("TXN-001"))

Using ABCMeta Directly

ABCMeta is the metaclass that powers ABCs. Inheriting from ABC is shorthand for setting metaclass=ABCMeta. Both are equivalent:

1234567891011
from abc import ABCMeta, abstractmethod # Using ABCMeta directly – equivalent to inheriting from ABC class PaymentProcessor(metaclass=ABCMeta): @abstractmethod def process(self, amount): pass @abstractmethod def refund(self, transaction_id): pass

Use ABC inheritance in almost all cases – it is cleaner and more readable. Use ABCMeta directly only when your class already inherits from another class that uses a different metaclass.

Inspecting Abstract Methods

__abstractmethods__ is a frozenset of method names that must be implemented before the class can be instantiated:

1234567891011121314151617
from abc import ABC, abstractmethod class ReportGenerator(ABC): @abstractmethod def generate(self, data): pass @abstractmethod def format_output(self, report): pass def save(self, path, content): with open(path, "w") as output_file: output_file.write(content) # Inspecting which methods are abstract print(ReportGenerator.__abstractmethods__) # frozenset({'generate', 'format_output'})

save is not abstract – it is a concrete method and does not appear in __abstractmethods__.

Partial Implementation

A subclass that implements only some abstract methods is itself abstract and cannot be instantiated:

1234567891011121314151617181920212223
from abc import ABC, abstractmethod class DataPipeline(ABC): @abstractmethod def extract(self): pass @abstractmethod def transform(self, data): pass @abstractmethod def load(self, data): pass # Partial implementation – still abstract class ExtractOnlyPipeline(DataPipeline): def extract(self): return [{"id": 1, "value": 100}, {"id": 2, "value": 200}] print(ExtractOnlyPipeline.__abstractmethods__) # frozenset({'transform', 'load'}) pipeline = ExtractOnlyPipeline() # TypeError – transform and load not implemented

This allows building intermediate abstract classes in a hierarchy – each layer can implement some methods while leaving others for deeper subclasses.

question mark

What does __abstractmethods__ contain on an abstract class?

Valitse oikea vastaus

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 1. Luku 2

Kysy tekoälyä

expand

Kysy tekoälyä

ChatGPT

Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme

Osio 1. Luku 2
some-alt