前言:
此刻朋友们对“python的元类”可能比较珍视,小伙伴们都想要知道一些“python的元类”的相关内容。那么小编在网摘上网罗了一些对于“python的元类””的相关内容,希望兄弟们能喜欢,咱们一起来了解一下吧!作者:麦叔
来源:麦叔编程
ABC是什么
我们来聊一个Python进阶话题,抽象基类,英文是Abstract Base Class,简称为ABC。
这个名字看起来很简单,ABC,但其实是Python进阶的重要知识点。提高Python设计能力的重要武器!
虽然Python相对Java等相对比较灵活。但要设计稍微复杂点的系统,高水平的设计者还是会使用一些设计技巧,比如使用ABC。至少Python内置集合类就大量使用了ABC。
简单来说,ABC是一种抽象的类,它只是规定了一些规范。要实现这个ABC的子类必须提供规范中要求的方法和属性。
我们来看例子吧。
设计场景
假设我们要开发一个媒体播放器。它可以播放不同的媒体格式。
在这种情况下,一个很好的选择就是创建一个ABC来声明子类需要提供的方法和属性。
一般的设计是这样的,让多个类都实现一个通用的函数,比如 play()。我们将媒体播放器定义为抽象类。每种特定的媒体文件格式(如mp4,MOV,AVI等)都可以提供抽象类的具体实现。
抽象类
下面是一个抽象类,它需要子类提供具体的方法实现和属性:
class MediaLoader(abc.ABC): @abc.abstractmethod def play(self) -> None: ... @property @abc.abstractmethod def ext(self) -> str: ...
abc.ABC是一个用于控制实体类创建的元类。Python的默认元类是type。默认的元类当创建实例的时候不会检查抽象方法。abc.ABC扩展了type,它会阻止我们为没有被完全实现的类创建实例。
抽象方法
抽象类中有两处使用了装饰器。一处使用@abc.abstractmethod ,另一处同时使用了@property和@abc.abstractmethod。Python广泛使用装饰器来修改函数或方法的功能。在这个例子中,它为元类ABC提供了额外的细节。因为我们标注了某个方法或属性是抽象的,子类必须实现相应的方法或属性才能成为有用的、可以被实例化的类。
抽象类的方法体是**...**。这个三点标记,即省略号,确实是合法的Python 代码,用以提醒我们:具体的子类需要实现相应的方法。
抽象属性
我们在ext()方法上也使用了@property装饰器。我们的目的是为了提供一个名为ext的字符串类型的类变量。使用@property把它声明为属性,这样子类可以选择使用简单的变量或者使用方法来实现这个属性。在实体类中使用简单变量可以满足抽象类的要求,也能通过mypy的类型检查。如果需要一些更复杂的计算,可以使用方法来替代简单的属性变量。
使用了这些标记的类会拥有了一个特殊的属性__abstractmethods__。这个属性会列出所有的抽象方法或属性:
>>> MediaLoader.__abstractmethods__frozenset({'ext', 'play'})测试一下
如果实现一个子类,会发生什么?我们看两个例子,一个反面例子Wav,它没有为抽象提供必要的实现。一个正面例子,它为抽象提供了具体实现。
>>> class Wav(MediaLoader): ... pass...>>> x = Wav() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't instantiate abstract class Wav with abstract methods ext, play >>> class Ogg(MediaLoader): ... ext = '.ogg' ... def play(self): ... pass...>>> o = Ogg()
子类Wav没有实现任何抽象方法。当我们尝试创建一个Wav类的实例时,抛出了异常。因为作为MediaLoader的子类,它没有实现ABC要求的规范,不能创建实例。
而子类Ogg提供了抽象属性的实现,所以它可以被实例化。
在创建复杂的应用时,这有明显的优势。像这样使用抽象类,可以确保子类符合规范,也可以让mypy很清楚地判断一个类是否实现了必要的方法和属性,在开发过程中为我们实时指出问题。
ABC你懂了吗?好啦,今天就聊到这里。如果喜欢,记得点赞!
CDA数据分析师分享案例,欢迎大家留言分享你的建议。
标签: #python的元类