python - Python 何时检查 ABC 的具体子类是否实现了所需的方法?
问题描述
在尝试编写单元测试来检查抽象基类的具体子类是否真的在实例化时引发 TypeError 如果未实现所需方法之一,我偶然发现了一些东西,这让我想知道何时检查所需的方法是否已定义由具体的子类实际执行。
到目前为止,我会说:在对象实例化时,因为这是在运行程序时实际引发异常的时间。
但是看看这个片段:
import abc
class MyABC(abc.ABC):
@abstractmethod
def foo(self): pass
MyConcreteSubclass(MyABC):
pass
正如预期的那样,尝试实例化 MyConcreteSubclass 会引发 TypeError:
>>> MyConcreteSubclass()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-39-fbfc0708afa6> in <module>()
----> 1 t = MySubclass()
TypeError: Can't instantiate abstract class MySubclass with abstract methods foo
但是如果我首先声明一个有效的子类然后删除这个方法会发生什么让我感到惊讶:
class MyConcreteSubclass(MyABC):
def foo(self):
print("bar")
MyConcreteSubclass.foo
--> <function __main__.MyConcreteSubclass.foo(self)>
>>> t = MyConcreteSubclass()
>>> t.foo()
bar
>>> del MyConcreteSubclass.foo
>>> MyConcreteSubclass.foo
<function __main__.MyABC.foo(self)>
>>> t = MyConcreteSubclass()
>>> print(t.foo())
None
这当然不是我所期望的。在删除后检查 MyConcreteSubclass.foo 时,我们看到通过方法 Resolution order 检索到了基类的 Abstract 方法,这与我们一开始没有在具体子类中实现 foo 的行为相同。
但是在实例化之后 TypeError 不会被引发。所以我想知道,当解释器评估具体子类的主体时,是否已经执行了所需方法的检查?如果是这样,为什么只有在有人尝试实例化子类时才会引发 TypeErrors?
上面显示的测试是使用 Python 3.6.5 执行的。
解决方案
它发生在类创建时。在 Python 3.7 中,它在 C 中,在compute_abstract_methods
in 中Modules/_abc.c
,被称为ABCMeta.__new__
.
顺便说一句,文档确实提到了
不支持向类动态添加抽象方法,或在方法或类创建后尝试修改其抽象状态。
推荐阅读
- python - 如何解析“嵌套”的 json 文件并导入 Pandas 数据框?
- coinbase-api - 如何使用 Coinbase Pro API 上的列表订单区分止损限价单和限价单
- r - R根据列表或列将文件移动到文件夹
- typescript - 正确输入 vuex getter 的 getters 参数
- sql-server - 如果在 SQL Server 中没有找到记录,则返回 null
- github-actions - 手动触发的 Github Action 总是被跳过
- django - 在 Django 中使用基于类的视图子类从 ajax 重定向路由
- python - 动态访问嵌套列表python中的元素
- python - 在 Python 中将字符串转换为绑定方法
- reactjs - Reactjs 从父级更新状态来自子级,而无需重新渲染父级