2012-11-19 90 views
1

我寫了下面的代碼,以幫助執行的某些方法的定義爲一類:A類強制實施方法定義

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。我正在做這個正確的方式嗎?我是否應該強制這樣的類模板?有沒有更好的方法來完成同樣的事情?

回答

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() 
+0

顯然,我可以花更多時間閱讀文檔 - 感謝您提供全面的答案。 –

4

可以使用ABCMeta元類:

MyClass
from abc import ABCMeta, abstractmethod 

class MyClass: 
    __metaclass__ = ABCMeta 

    @abstractmethod 
    def foo(self): 
     pass 

子類必須覆蓋foo被允許進行實例化。

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