一、提要

        一个抽象类可以被认为是其他类的蓝图。它允许您创建一组必须在从抽象类构建的任何子类中创建的方法。包含一个或多个抽象方法的类称为抽象类。抽象方法是具有声明但没有实现的方法。在设计大型功能单元时,我们使用抽象类。当我们想为组件的不同实现提供通用接口时,我们使用抽象类。

二、在Python用抽象类

2.1 为什么使用抽象基类

        通过定义一个抽象基类,您可以为一组子类定义一个通用的应用程序接口(API)。此功能在第三方将提供实现的情况下特别有用,例如使用插件,但也可以在大型团队或大型代码库中为您提供帮助,因为您很难记住所有类或不可能。

2.2 抽象基类如何工作

        默认情况下,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

结论:

  • 用抽象类必须从abc包的ABC获取
  • @abstractmethod指定抽象方法

  
示例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

结论:

  • 用抽象类从abc包的ABC继承类已经注册为抽象类
  • @abstractmethod指定抽象类
  • 实际抽象类似乎与一般类无异,但将来可能随python的发展而扩张。

2.3 通过子类化实现

        通过直接从基类子类化,我们可以避免显式注册类的需要。在这种情况下,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: 
True

True

        使用直接子类化的一个副作用是,可以通过向基类询问从它派生的已知类的列表来找到插件的所有实现。

  

2.4 抽象基类中的具体方法

        具体类只包含具体(普通)方法,而抽象类可能同时包含具体方法和抽象方法。具体类提供抽象方法的实现,抽象基类也可以通过 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 Class

subclass

在上面的程序中,我们可以使用 super() 来调用抽象类中的方法。

2.5 抽象属性

        抽象类除了方法之外还包括属性,您可以通过使用@abstractproperty 定义具体类中的属性。

# Python program showing

# abstract properties

import abc

from abc import ABC, abstractmethod

class parent(ABC):

    @abc.abstractproperty

    def geeks(self):

        return "parent class"

class child(parent):

      

    @property

    def geeks(self):

        return "child class"

  

  

try:

    r =parent()

    print( r.geeks)

except Exception as err:

    print (err)

  

r = child()

print (r.geeks)

Output: 
 

Can't instantiate abstract class parent with abstract methods geeks
child class

在上面的示例中,无法实例化 Base 类,因为它只有属性 getter 方法的抽象版本。

2.6 抽象类实例化

        抽象类是不完整的,因为它们有没有人的方法。如果 python 允许为抽象类创建对象,那么如果有人调用抽象方法,则使用该对象,但没有要调用的实际实现。所以我们使用一个抽象类作为模板,并根据需要,在使用它之前对其进行扩展和构建。由于事实上,抽象类不是具体类,它不能被实例化。当我们为抽象类创建对象时,它会引发错误。 

 Python program showing

# abstract class cannot

# be an instantiation

from abc import ABC,abstractmethod

class Animal(ABC):

    @abstractmethod

    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")

c=Animal()

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

更多推荐

【Python知识】谈谈Python的抽象类