这是我发现的:如果您将__abstractmethods__
属性设置为空集,您将能够实例化抽象类。此行为在PEP 3119中指定:
如果结果__abstractmethods__
集非空,则该类被认为是抽象的,并且尝试实例化它会引发 TypeError。
所以你只需要在测试期间清除这个属性。
>>> import abc
>>> class A(metaclass = abc.ABCMeta):
... @abc.abstractmethod
... def foo(self): pass
你不能实例化A:
>>> A()
Traceback (most recent call last):
TypeError: Can't instantiate abstract class A with abstract methods foo
如果您覆盖__abstractmethods__
,您可以:
>>> A.__abstractmethods__=set()
>>> A() #doctest: +ELLIPSIS
<....A object at 0x...>
它适用于两种方式:
>>> class B(object): pass
>>> B() #doctest: +ELLIPSIS
<....B object at 0x...>
>>> B.__abstractmethods__={"foo"}
>>> B()
Traceback (most recent call last):
TypeError: Can't instantiate abstract class B with abstract methods foo
您还可以使用unittest.mock
(从 3.3 开始)临时覆盖 ABC 行为。
>>> class A(metaclass = abc.ABCMeta):
... @abc.abstractmethod
... def foo(self): pass
>>> from unittest.mock import patch
>>> p = patch.multiple(A, __abstractmethods__=set())
>>> p.start()
{}
>>> A() #doctest: +ELLIPSIS
<....A object at 0x...>
>>> p.stop()
>>> A()
Traceback (most recent call last):
TypeError: Can't instantiate abstract class A with abstract methods foo