@abstractmethod 是 Python 标準库中的一个装饰器,位于 abc 模组内,用来定义 抽象方法 (abstract methods)。抽象方法是指必须在子类别中实作的方法,而在基类 (abstract base class, ABC) 中只能定义方法名称和规范,不能有具体的实作内容。
使用 @abstractmethod 可以确保某些方法在子类别中被实作,否则子类别无法被实例化。
- 强制规范子类别行为:定义出子类别必须实作的方法,确保程式的一致性。
- 设计更清晰的接口:提供方法签名的模板,指导子类别的开发。
- 避免基类被实例化:基类仅作为框架存在,防止直接使用。
- ABC 是 Python 的内建抽象基类,它用来辅助定义抽象类别。
- @abstractmethod 装饰器标注抽象方法。范例
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass # 不定义具体实作,只是声明
@abstractmethod
def move(self):
pass
# Animal 是抽象类别,无法直接实例化
# animal = Animal() # TypeError: Can\'t instantiate abstract class Animal with abstract methods
子类别必须实作所有抽象方法,否则无法实例化
class Dog(Animal):
def sound(self):
return "Woof!"
def move(self):
return "Run"
dog = Dog()
print(dog.sound()) # Woof!
print(dog.move()) # Run
范例
class Shape(ABC):
def description(self):
return "This is a shape."
@abstractmethod
def area(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
rect = Rectangle(4, 5)
print(rect.description()) # This is a shape.
print(rect.area()) # 20
范例
class Payment(ABC):
@abstractmethod
def pay(self, amount):
pass
class CreditCardPayment(Payment):
def pay(self, amount):
return f"Paid {amount} using Credit Card."
class PayPalPayment(Payment):
def pay(self, amount):
return f"Paid {amount} using PayPal."
# 支付方式可依不同类别动态改变
def process_payment(payment: Payment, amount):
print(payment.pay(amount))
process_payment(CreditCardPayment(), 100) # Paid 100 using Credit Card.
process_payment(PayPalPayment(), 200) # Paid 200 using PayPal.
范例
class Animal(ABC):
@abstractmethod
def sound(self):
pass
class Cat(Animal):
def sound(self):
super().sound() # 调用基类的空方法(仅示例,实际基类方法通常有意义)
return "Meow!"
cat = Cat()
print(cat.sound()) # Meow!
范例
class Vehicle(ABC):
@property
@abstractmethod
def wheels(self):
pass
class Car(Vehicle):
@property
def wheels(self):
return 4
car = Car()
print(car.wheels) # 4
- 为什么基类无法实例化?如果基类中有未实作的抽象方法,则基类是抽象类别,无法直接使用。
- 可以只实作部分抽象方法吗?不行。子类别必须实作所有的抽象方法,否则子类别也会成为抽象类别,无法被实例化。
- 抽象类别可以有初始化方法 (init) 吗?可以,抽象类别的初始化方法可以用于设置通用属性,并被子类别继承。
总结
@abstractmethod 是 Python 中用来声明抽象方法的装饰器。它强制子类别实作方法,确保程序设计的规范性和一致性。抽象基类通常用于定义接口,促进多型行为。