我编写了以下代码来帮助强制执行类的某些方法的定义:
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。我是否正确地走这条路?我是否应该强制像这样的类模板?是否有更好的方法来完成同样的事情?
答案 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