Defining ABCs with the abc Module
Svep för att visa menyn
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:
1234567891011121314151617181920212223from 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:
1234567891011from 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:
1234567891011121314151617from 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:
1234567891011121314151617181920212223from 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.
Tack för dina kommentarer!
Fråga AI
Fråga AI
Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal