【发布时间】:2016-08-01 20:12:56
【问题描述】:
我编写了一个元类,它在运行时自动将其类注册到字典中。为了使其正常工作,它必须能够忽略抽象类。
代码在 Python 2 中运行良好,但我在尝试使其与 Python 3 兼容时遇到了困难。
这是当前代码的样子:
def AutoRegister(registry, base_type=ABCMeta):
class _metaclass(base_type):
def __init__(self, what, bases=None, attrs=None):
super(_metaclass, self).__init__(what, bases, attrs)
# Do not register abstract classes.
# Note that we do not use `inspect.isabstract` here, as
# that only detects classes with unimplemented abstract
# methods - which is a valid approach, but not what we
# want here.
# :see: http://stackoverflow.com/a/14410942/
metaclass = attrs.get('__metaclass__')
if not (metaclass and issubclass(metaclass, ABCMeta)):
registry.register(self)
return _metaclass
在 Python 2 中的用法如下所示:
# Abstract classes; these are not registered.
class BaseWidget(object): __metaclass__ = AutoRegister(widget_registry)
class BaseGizmo(BaseWidget): __metaclass__ = ABCMeta
# Concrete classes; these get registered.
class AlphaWidget(BaseWidget): pass
class BravoGizmo(BaseGizmo): pass
不过,我不知道如何在 Python 3 中实现这一点。
元类如何确定它是否在 Python 3 中初始化抽象类?
【问题讨论】:
-
尽管使用了
ABCMeta,但您展示的 Python 2 代码中的所谓“抽象”类实际上并不是抽象的(也就是说,您可以根据需要创建它们的实例,而 Python 不会引发异常)。对于真正抽象的东西,您需要在您在其中声明的某些方法上使用@abstractmethod装饰器。子类也将是抽象的,除非它们覆盖这些方法(不使用装饰器本身)。如果不先解决这个基本问题,我不确定是否可以对您的问题给出合理的答案。 -
感谢您的意见。您的评论促使我做一些进一步的研究,我现在看到我对“抽象”的最初理解是不正确的。我得考虑一下;我们在代码库中经常使用这种模式,但如果我们最终以错误的方式使用工具,从长远来看,这将导致重大问题。