Python 的 ABC 入门
Python 的 ABC 基础知识是什么?它代表抽象基类,是Python类中基于抽象的概念。抽象是面向对象编程的一个组成部分。
抽象就是我们所说的向用户隐藏程序的内部过程。以计算机鼠标为例,我们单击左键或右键,就会发生相应的操作,或者滚动鼠标滚轮,就会发生特定的任务。我们不知道内部功能,但我们确实知道单击此按钮即可完成我们的工作。
抽象地讲,用户不知道内部功能,但熟悉该方法的用途。如果我们以模块为例datetime
,我们确实知道运行该datetime.now()
函数将返回当前日期和时间,但不知道这是如何发生的。
Python 中的ABC
Python 不是一种完全面向对象的编程语言,但它支持抽象类和抽象等功能。我们无法直接在Python中创建抽象类,因此Python提供了一个名为abc的模块,它提供了定义抽象基类(ABC)的基础结构。
什么是抽象基类?它们为具体的类提供了蓝图。它们只是定义但没有实现,而是需要子类来实现。
定义ABC
让我们通过一个例子来了解如何定义一个带有抽象方法的抽象类。
from abc import ABC, abstractmethod
class Friend(ABC):
@abstractmethod
def role(self):
pass
类Friend派生自模块ABC
中的类abc
,使其成为抽象类,然后在该类中@abstractmethod
定义了一个装饰器来指示该函数角色是一个抽象方法。
abc
模块有另一个类ABCMeta
用于创建抽象类。
from abc import ABCMeta, abstractmethod
class Friend(metaclass=ABCMeta):
@abstractmethod
def role(self):
pass
ABC在行动
现在我们将了解如何创建抽象类和抽象方法,然后通过继承在具体类中实现它。
from abc import ABC, abstractmethod
# Defining abstract class
class Friends(ABC):
"""abstract method decorator to indicate that the
method right below is an abstract method."""
@abstractmethod
def role(self):
pass
# Concrete derived class inheriting from abstract class
class Sachin(Friends):
# Implementing abstract method
def role(self):
print('Python Developer')
# Concrete derived class inheriting from abstract class
class Rishu(Friends):
# Implementing abstract method
def role(self):
print('C++ Developer')
# Concrete derived class inheriting from abstract class
class Yashwant(Friends):
# Implementing abstract method
def role(self):
print('C++ Developer')
# Instantiating concrete derived class
roles = Sachin()
roles.role()
# Instantiating concrete derived class
roles = Rishu()
roles.role()
# Instantiating concrete derived class
roles = Yashwant()
roles.role()
在上面的代码中,我们创建了一个名为 的抽象类,并使用装饰器在类中Friends
定义了抽象方法。role
@abstractmethod
然后我们创建了三个具体的派生类 、Sachin
、Rishu
和Yashwant
,它们继承自该类并在其中Friends
实现了抽象方法。role
然后我们实例化派生类并调用role
使用类的实例来显示结果。
Python Developer
C++ Developer
C++ Developer
正如我们之前讨论的,抽象类提供了将方法实现到具体子类中的蓝图。
from abc import ABC, abstractmethod
class Details(ABC):
@abstractmethod
def getname(self):
return self.name
@abstractmethod
def getrole(self):
return self.role
@abstractmethod
def gethobby(self):
return self.hobby
class Sachin(Details):
def __init__(self, name="Sachin"):
self.name = name
self.role = "Python Dev"
self.hobby = "Fuseball spielen"
def getname(self):
return self.name
def getrole(self):
return self.role
def gethobby(self):
return self.hobby
detail = Sachin()
print(detail.getname())
print(detail.getrole())
print(detail.gethobby())
在上面的代码中,我们为类创建了一个蓝图Details
。然后我们创建了一个Sachin
继承自 的类Details
,并根据蓝图实现了方法。
然后我们实例化该类,然后打印、和Sachin
的值。getname
getrole
gethobby
Sachin
Python Dev
Fuseball spielen
如果我们创建一个不遵循抽象类蓝图的类怎么办?
from abc import ABC, abstractmethod
class Details(ABC):
@abstractmethod
def getname(self):
return self.name
@abstractmethod
def getrole(self):
return self.role
@abstractmethod
def gethobby(self):
return self.hobby
class Sachin(Details):
def __init__(self, name="Sachin"):
self.name = name
self.role = "Python Dev"
self.hobby = "Fuseball spielen"
def getname(self):
return self.name
def getrole(self):
return self.role
detail = Sachin()
print(detail.getname())
print(detail.getrole())
Python 在执行上述代码时会引发错误,因为该类Sachin
不遵循类Details
蓝图。
Traceback (most recent call last):
....
TypeError: Can't instantiate abstract class Sachin with abstract method gethobby
ABC的使用
正如我们在上面的示例中看到的,如果派生类不遵循抽象类的蓝图,则会引发错误。
这就是 ABC(抽象基类)在确保子类必须遵循该蓝图方面发挥重要作用的地方。因此我们可以说,从抽象类继承的子类必须遵循相同的结构并实现抽象方法。
ABC里面的具体方法
我们还可以在抽象类中定义具体方法。具体方法是有完整定义的普通方法。
from abc import ABC, abstractmethod
# Abstract class
class Demo(ABC):
# Defining a concrete method
def concrete_method(self):
print("Calling concrete method")
@abstractmethod
def data(self):
pass
# Derived class
class Test(Demo):
def data(self):
pass
# Instantiating the class
data = Test()
# Calling the concrete method
data.concrete_method()
在上面的代码中,concrete_method
是在抽象类中定义的具体方法,并且使用类 Test 的实例调用该方法。
Calling concrete method
抽象类实例化
抽象类只能被定义而不能被实例化,因为它们不是具体类。Python 不允许为抽象类创建对象,因为没有实际的实现可以调用,而是需要子类来实现。
from abc import ABC, abstractmethod
class Details(ABC):
@abstractmethod
def getname(self):
return self.name
@abstractmethod
def getrole(self):
return self.role
class Sachin(Details):
def __init__(self, name="Sachin"):
self.name = name
self.role = "Python Dev"
def getname(self):
return self.name
def getrole(self):
return self.role
# Instantiating the abstract class
abstract_class = Details()
输出
Traceback (most recent call last):
....
TypeError: Can't instantiate abstract class Details with abstract methods getname, getrole
我们收到错误消息,指出我们无法使用名为getname
和的抽象方法实例化抽象类Details getrole
。
抽象属性
正如abc
模块允许我们使用装饰器定义抽象方法一样@abstractmethod
,它也允许我们使用装饰器定义抽象属性@abstractproperty
。
from abc import ABC, abstractproperty
# Abstract class
class Hero(ABC):
@abstractproperty
def hero_name(self):
return self.hname
@abstractproperty
def reel_name(self):
return self.rname
# Derived class
class RDJ(Hero):
def __init__(self):
self.hname = "IronMan"
self.rname = "Tony Stark"
@property
def hero_name(self):
return self.hname
@property
def reel_name(self):
return self.rname
data = RDJ()
print(f'The hero name is: {data.hero_name}')
print(f'The reel name is: {data.reel_name}')
我们创建了一个抽象类 Hero 并定义了两个名为hero_name
和reel_name
using的抽象属性@abstractproperty
。然后,在派生类中RDJ
,我们使用@property
装饰器来实现它们,这将使它们成为 getter 方法。
然后我们实例化该类并使用该类实例来访问和RDJ
的值。hero_name
reel_name
The hero name is: IronMan
The reel name is: Tony Stark
如果我们没有将@property
装饰器放在类中RDJ
,我们就必须调用hero_name
and reel_name
。
from abc import ABC, abstractproperty
# Abstract class
class Hero(ABC):
@abstractproperty
def hero_name(self):
return self.hname
@abstractproperty
def reel_name(self):
return self.rname
# Derived class
class RDJ(Hero):
def __init__(self):
self.hname = "IronMan"
self.rname = "Tony Stark"
def hero_name(self):
return self.hname
def reel_name(self):
return self.rname
data = RDJ()
print(f'The hero name is: {data.hero_name()}')
print(f'The reel name is: {data.reel_name()}')
----------
The hero name is: IronMan
The reel name is: Tony Stark
注意:abstractproperty
是一个已弃用的类,我们可以使用@property
with@abstractmethod
来定义抽象属性。Pycharm IDE 在使用该类时发出警告abstractproperty
。
如果我们修改上面的代码,就会像下面这样。
# Abstract class
class Hero(ABC):
@property
@abstractmethod
def hero_name(self):
return self.hname
@property
@abstractmethod
def reel_name(self):
return self.rname
只需在抽象类中应用上面代码中所示的修改并运行代码即可。该代码将像之前一样运行,不会出现任何错误。
结论
我们在本文中介绍了抽象类、抽象方法和抽象属性的基础知识。Python 有一个abc
模块,提供用于定义抽象基类的基础结构。
ABC
模块中的类可abc
用于创建抽象类。ABC
是一个辅助类,ABCMeta
其元类,我们还可以通过传递metaclass
关键字并使用 来定义抽象类ABCMeta
。这两个类之间的唯一区别是ABCMeta
具有附加功能。
创建抽象类后,我们使用@abstractmethod
and ( @property
with @abstractmethod
) 装饰器来定义类中的抽象方法和抽象属性。
为了理解该理论,我们在解释的同时编写了示例。
- 点赞
- 收藏
- 关注作者
评论(0)