我一直在尝试一些abc
python 中的模块。阿拉
>>> import abc
在正常情况下,如果 ABC 类包含未实现的类,则您希望它不会被实例化abstractmethod
。你知道如下:
>>> class MyClass(metaclass=abc.ABCMeta):
... @abc.abstractmethod
... def mymethod(self):
... return -1
...
>>> MyClass()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MyClass with abstract methods mymethod
OR 对于任何派生类。一切似乎都工作正常,直到你继承了某些东西......说dict
or list
如下:
>>> class YourClass(list, metaclass=abc.ABCMeta):
... @abc.abstractmethod
... def yourmethod(self):
... return -1
...
>>> YourClass()
[]
这很令人惊讶,因为type
无论如何,这可能是主要工厂或元类的东西,所以我从以下内容中假设。
>>> type(abc.ABCMeta)
<class 'type'>
>>> type(list)
<class 'type'>
通过一些调查,我发现它可以归结为简单的事情,比如添加一个__abstractmethod__
类的属性'object
休息自然发生:
>>> class AbstractClass:
... pass
...
>>> AbstractClass.__abstractmethods__ = {'abstractmethod'}
>>> AbstractClass()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class AbstractClass with abstract methods abstractmethod
因此,人们可以通过故意覆盖来避免检查__new__
方法及清理__abstractmethods__
如下:
>>> class SupposedlyAbstractClass(metaclass=abc.ABCMeta):
... def __new__(cls):
... cls.__abstractmethods__ = {}
... return super(AbstractClass, cls).__new__(cls)
... @abc.abstractmethod
... def abstractmethod(self):
... return -1
...
>>> SupposedlyAbstractClass()
<__main__.SupposedlyAbstractClass object at 0x000001FA6BF05828>
正如我亲自检查过的,这种行为在 Python 2.7 和 Python 3.7 中是相同的。我不知道这对于所有其他 python 实现是否相同。
最后,回到问题......为什么会这样?我们永远不应该用抽象类来创建抽象类是明智的吗?list
, tuple
or dict
?或者我应该继续添加一个__new__
类方法检查__abstractmethods__
在实例化之前?