了解python中的元类

时间:2018-07-18 07:18:41

标签: python python-3.6 metaclass

我正尝试在python中学习metaclasses,根据研究发现,我发现了以下示例。

我有一个BaseDerived类,例如follow

class Base():
    def foo(self):
        return self.bar() 

class Derived(Base):
    def foo2(self):
        return "i am foo2"

现在,当我要确保扩展Base类的任何人都必须实现bar()方法时,我创建了元类来挂钩派生类的构造,所以现在{{ 1}}类看起来像跟着Base元类。

BaseMeta

问题是当我查看正文时,它会返回class BaseMeta(type): def __new__(cls, name, bases, body): if not "bar" in body: raise TypeError("bar not implemented") return super().__new__(cls, name, bases, body) class Base(metaclass=BaseMeta): def foo(self): return self.bar() Base类的2条记录,如下所示。

Derived

由于 {'__module__': '__main__', '__qualname__': 'Base', 'foo': <function Base.foo at 0x7ffbaae436a8>} {'__module__': '__main__', '__qualname__': 'Derived', 'bar': <function Derived.bar at 0x7ffbaae437b8>} 没有__new__,所以Base中的代码中断了,但是我只想检查Derived类,所以我像下面那样重写了bar

metaclass

我正在用def __new__(cls, name, bases, body): if name !="Base" and not "bar" in body: raise TypeError("bar not implemented") return super().__new__(cls, name, bases, body) 方法检查name != Base

  

是正确的方法还是我们可以使用其他最佳方法?

1 个答案:

答案 0 :(得分:2)

您可以使用stdlib中的abc模块,该模块具有执行此操作的工具。 https://docs.python.org/3/library/abc.html

import abc

class Base(abc.ABC):

    @abc.abstractmethod
    def bar(self):
         pass

class Derived(Base):
    pass

# This will raise an error because foo is not implemented
# >>> Derived() 
# TypeError: Can't instantiate abstract class Derived with abstract methods bar

另一种策略是在您的基类上使用一个bar方法,该方法会引发NotImplementedError。主要区别在于,除非您实际调用需要bar的东西,否则不会引发错误。例如

class Base():
    def foo(self):
        return self.bar() 

    def bar(self):
        raise NotImplementedError