强制类的实现方法定义

时间:2012-11-19 13:40:56

标签: python

我编写了以下代码来帮助强制执行类的某些方法的定义:

def createClassTemplate(name, requiredMethods=[], inherits=object):
    def require(name):
        def errorRaiser(self, *args, **kwargs):
            raise RequireException("method '{}' must be defined.".format(name))
        setattr(wrapper, "__name__", name)
        return errorRaiser

    class Custom(inherits): pass

    setattr(Custom, "__name__", name)
    for methodName in requiredMethods:
        setattr(Custom, methodName, require(methodName))

    return Custom

这是这样实现的:

Model = createClassTemplate("Model", ["foo", "bar", "baz"])

class MyClass(Model):
    pass

这样,当我缺少一个方法时,调用类将生成一个有意义的错误,表明我未能定义所需的方法。

问题是,上面的代码似乎令人不舒服的hacky和unpythonic。我是否正确地走这条路?我是否应该强制像这样的类模板?是否有更好的方法来完成同样的事情?

4 个答案:

答案 0 :(得分:4)

您可以使用ABCMeta元类:

from abc import ABCMeta, abstractmethod

class MyClass:
    __metaclass__ = ABCMeta

    @abstractmethod
    def foo(self):
        pass

MyClass的子类必须覆盖foo以允许实例化。

答案 1 :(得分:2)

您应该使用metaclass代替。

标准库附带了一个现成的元类,仅用于此任务,ABCMeta metaclass

import abc

class Model(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def foo(self):
        pass

    @abc.abstractmethod
    def bar(self):
        pass

    @abc.abstractmethod
    def baz(self):
        pass

class MyClass(Model):
    pass

演示:

>>> import abc
>>> class Model(object):
...     __metaclass__ = abc.ABCMeta
...     @abc.abstractmethod
...     def foo(self):
...         pass
...     @abc.abstractmethod
...     def bar(self):
...         pass
...     @abc.abstractmethod
...     def baz(self):
...         pass
... 
>>> class MyClass(Model):
...     pass
... 
>>> myclass = MyClass()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MyClass with abstract methods bar, baz, foo

一旦MyClass确实提供了抽象方法的实现,实例化就会成功:

>>> class MyClass(Model):
...     def foo(self): pass
...     def bar(self): pass
...     def baz(self): pass
... 
>>> myclass = MyClass()

答案 2 :(得分:0)

如果你使用的是Python 2.6+,那就是ABC的概念 - http://docs.python.org/2/library/abc.html

答案 3 :(得分:0)

在我看来,你正试图重新发明Abstract Base Classes

我想你想要这样的东西:

import abc

class MyBaseClass:
    __metaclass__ = abc.ABCMeta
    @abc.abstractmethod
    def foo(self):
        pass

    @abc.abstractmethod
    def bar(self):
        pass

    @abc.abstractmethod
    def baz(self):
        pas