2021-10-22

PEP 3119 -- 引入抽象基类
PEP: 3119
Title: 引入抽象基类
Author: Guido van Rossum , Talin
Status: Final
Type: Standards Track
Created: 18-Apr-2007
Post-History: 26-Apr-2007, 11-May-2007

目录

摘要
致谢
基本原理
详述
ABCs vs Alternative
ABCs vs Duck Typing
ABCs vs. Generic Functions
ABCs vs. Interfaces
参考文献
版权声明
摘要

这是一个为Python3000增加抽象基类(abc)支持的建议。建议包括:

  • 重载 isinstance()issubclass() 的方式
  • 一个作为abc支持框架的新模块 abc。它定义基于ABC的元类,以及可以声明抽象方法的装饰器
  • 容器和迭代器特定的ABCs,将添加到 collections 模块中

与接口、泛型函数相比,提案中的多数想法不是关于ABCs的具体的机制,而是关于诸如“什么构成一个集合(set)”, “什么构成映射(map)”、“什么构成一个序列(sequence)”这样的哲学问题的澄清

还有个一个配套的PEP PEP 3141,它定义了数字类型的ABCs

基本原理

在面向对象编程领域中,与对象交互的使用模式可以分为两个基本的类别,即“调用”和“检查”。

调用模式指通过调用一个对象的方法与对象进行交互。一般与多态性相结合,调用一个给定的方法可能会根据对象的类型运行不同的代码。

检查模式是指外部代码(对象的方法之外)能够检查该对象的类型或属性,并根据获得的信息决定如何处理该对象

两种使用模式都服务于大致相同的目的,即,能够以统一的方式来支持对不同的、以及可能是全新的对象的处理,但同时,允许为不同类型的对象定制各自的处理逻辑。

在经典的 OOP 理论中,调用是首选的使用模式,并且极不鼓励使用检查模式,因为它被认为是早期过程式编程风格的遗物。然而,在实践中,这种观点过于教条和僵硬,并导致了一种与 Python 等语言的动态特性非常不符的设计僵化。

特别是,经常会有这样的需求:用对象类的创建者没有预料到的方式来处理对象。在对象中尽可能预置方法中来满足该对象的每个可能用户的所有需求,并不总是最好的解决方案。此外,有许多强大的调度哲学和这种把行为严格封装在对象里面的的经典 OOP 要求形成直接冲突,例如模式或规则匹配驱动的逻辑。

另一方面,经典的OOP理论家对检查模式的批评之一是,被检查的内容缺少规范约束和特殊的性质。在像 Python 这样的语言中,对象的几乎任何属性都可以被外部代码反射和直接访问,有许多不同的方法来测试对象是否符合特定协议。例如,如果询问“这个对象是可变序列容器吗?”,你可以查找“list”的基类,或者查找名为“getitem”的方法。但请注意,尽管这些检测看起来很明显,但它们都不正确,因为一个会产生假阴性,而另一个会产生假阳性。

被普遍认同的一个补救措施是将检测标准化,并将它们分组到一个整齐的排列中。最容易做到这一点的方法是,通过将一组标准的可检测属性与每个类关联起来,或者通过继承机制以及一些其他方式。每个检测都包含一系列的承诺:关于类的一般行为的承诺,以及关于哪些其他类方法可用的承诺。

该 PEP 提出了一种用于组织这些检测的特定策略,我们称之为抽象基类ABC。 ABC 只是 Python 类,它们被添加到对象的继承树中,以向外部检查器发送该对象的某些特性。检测是使用 isinstance() 完成的,特定 ABC 的存在意味着检测已经通过。

此外,ABC 定义了一个最小的方法集,用于建立类型的特征行为。根据 ABC 类型区分对象的代码可以确信这些方法将会始终存在。这些方法中的每一个都伴随着一个通用的抽象语义定义,该定义在 ABC 的文档中进行了描述。这些标准语义定义不是强制执行的,但强烈建议使用。

像 Python 中的所有其他东西一样,这些承诺具有君子协议的性质,这意味着虽然语言层面确实执行了 ABC 做出的一些承诺,但其他剩余的,由具体类的实现者来确保保留剩余的。

你可能感兴趣的:(2021-10-22)