一个抽象类可以被认为是其他类的蓝图。它允许您创建一组必须在从抽象类构建的任何子类中创建的方法。包含一个或多个抽象方法的类称为抽象类。抽象方法是具有声明但没有实现的方法。在设计大型功能单元时,我们使用抽象类。当我们想为组件的不同实现提供通用接口时,我们使用抽象类。
通过定义一个抽象基类,您可以为一组子类定义一个通用的应用程序接口(API)。此功能在第三方将提供实现的情况下特别有用,例如使用插件,但也可以在大型团队或大型代码库中为您提供帮助,因为您很难记住所有类或不可能。
默认情况下,Python 不提供抽象类。 Python 附带一个模块,该模块为定义抽象基类(ABC)提供了基础,该模块名称为 ABC。 ABC 的工作方式是将基类的方法装饰为抽象,然后将具体类注册为抽象基的实现。当使用关键字@abstractmethod 修饰时,方法变得抽象。例如 -
示例1:下面代码表示几何种多边形的抽象类
- from abc import ABC, abstractmethod
-
-
- class Polygon(ABC):
- @abstractmethod
- def noofsides(self):
- pass
-
- class Triangle(Polygon):
- # overriding abstract method
- def noofsides(self):
- print("I have 3 sides")
-
- class Pentagon(Polygon):
- # overriding abstract method
- def noofsides(self):
- print("I have 5 sides")
-
- class Hexagon(Polygon):
- # overriding abstract method
- def noofsides(self):
- print("I have 6 sides")
-
- class Quadrilateral(Polygon):
- # overriding abstract method
- def noofsides(self):
- print("I have 4 sides")
-
- # Driver code
-
- R = Triangle()
- R.noofsides()
- K = Quadrilateral()
- K.noofsides()
- R = Pentagon()
- R.noofsides()
- K = Hexagon()
- K.noofsides()
Output:
I have 3 sides
I have 4 sides
I have 5 sides
I have 6 sides
结论:
示例2: 这里加与不加@abstractmethod,似乎没什么差别
- # Python program showing
- # abstract base class work
-
-
- from abc import ABC, abstractmethod
-
- class Animal(ABC):
- def move(self):
- pass
-
- class Human(Animal):
- def move(self):
- print("I can walk and run")
-
- class Snake(Animal):
- def move(self):
- print("I can crawl")
-
- class Dog(Animal):
- def move(self):
- print("I can bark")
-
-
- class Lion(Animal):
- def move(self):
- print("I can roar")
-
-
-
- # Driver code
- R = Human()
- R.move()
- K = Snake()
- K.move()
- R = Dog()
- R.move()
- K = Lion()
- K.move()
Output:
I can walk and run
I can crawl
I can bark
I can roar
结论:
通过直接从基类子类化,我们可以避免显式注册类的需要。在这种情况下,Python 类管理用于将 PluginImplementation 识别为实现抽象 PluginBase。
Python3
- # Python program showing
- # implementation of abstract
- # class through subclassing
- import abc
-
- class parent:
- def geeks(self):
- pass
-
- class child(parent):
- def geeks(self):
- print("child class")
-
- # Driver code
- print( issubclass(child, parent))
- print( isinstance(child(), parent))
Output:
TrueTrue
使用直接子类化的一个副作用是,可以通过向基类询问从它派生的已知类的列表来找到插件的所有实现。
具体类只包含具体(普通)方法,而抽象类可能同时包含具体方法和抽象方法。具体类提供抽象方法的实现,抽象基类也可以通过 super() 调用方法来提供实现。
让我们看一下使用 super() 调用方法的示例:
- # Python program invoking a
- # method using super()
- import abc
-
- from abc import ABC, abstractmethod
- class R(ABC):
- def rk(self):
- print("Abstract Base Class")
-
- class K(R):
- def rk(self):
- super().rk()
- print("subclass ")
-
- # Driver code
- r = K()
- r.rk()
Output:
Abstract Base Classsubclass
在上面的程序中,我们可以使用 super() 来调用抽象类中的方法。
抽象类除了方法之外还包括属性,您可以通过使用@abstractproperty 定义具体类中的属性。
|
Output:
Can't instantiate abstract class parent with abstract methods geeks child class
在上面的示例中,无法实例化 Base 类,因为它只有属性 getter 方法的抽象版本。
抽象类是不完整的,因为它们有没有人的方法。如果 python 允许为抽象类创建对象,那么如果有人调用抽象方法,则使用该对象,但没有要调用的实际实现。所以我们使用一个抽象类作为模板,并根据需要,在使用它之前对其进行扩展和构建。由于事实上,抽象类不是具体类,它不能被实例化。当我们为抽象类创建对象时,它会引发错误。
|
Output:
Traceback (most recent call last): File "/home/ffe4267d930f204512b7f501bb1bc489.py", line 19, in c=Animal() TypeError: Can't instantiate abstract class Animal with abstract methods move