Python中字段的NotImplementedError等价
在Python 2.x中,当你想把一个方法标记为抽象的,你可以像这样定义它:
class Base: def foo(self): raise NotImplementedError("Subclasses should implement this!")
那么如果你忘记重写它,你会得到一个很好的提醒exception。 有没有一种等同的方式来标记一个领域是抽象的? 或者在class级文档中说明所有你能做的事情?
起初我以为我可以把这个字段设置为NotImplemented,但是当我查找它的实际内容(比较富有)时,它似乎是一种滥用。
是的你可以。 使用@property
装饰器。 例如,如果你有一个名为“example”的字段,那么你不能做这样的事情:
class Base(object): @property def example(self): raise NotImplementedError("Subclasses should implement this!")
运行以下命令会产生一个NotImplementedError
,就像你想的那样。
b = Base() print b.example
备选答案:
@property def NotImplementedField(self): raise NotImplementedError class a(object): x = NotImplementedField class b(a): # x = 5 pass b().x a().x
这就像埃文的,但简洁而又便宜 – 你只会得到一个NotImplementedField的实例。
def require_abstract_fields(obj, cls): abstract_fields = getattr(cls, "abstract_fields", None) if abstract_fields is None: return for field in abstract_fields: if not hasattr(obj, field): raise RuntimeError, "object %s failed to define %s" % (obj, field) class a(object): abstract_fields = ("x", ) def __init__(self): require_abstract_fields(self, a) class b(a): abstract_fields = ("y", ) x = 5 def __init__(self): require_abstract_fields(self, b) super(b, self).__init__() b() a()
请注意将类types传递到require_abstract_fields
,所以如果多个inheritance类使用这个类,它们不会全部validation最派生类的字段。 你也许可以用元类自动化这个,但是我没有深入。 定义一个字段为None被接受。
这是我的解决scheme:
def not_implemented_method(func): from functools import wraps from inspect import getargspec, formatargspec @wraps(func) def wrapper(self, *args, **kwargs): c = self.__class__.__name__ m = func.__name__ a = formatargspec(*getargspec(func)) raise NotImplementedError('\'%s\' object does not implement the method \'%s%s\'' % (c, m, a)) return wrapper def not_implemented_property(func): from functools import wraps from inspect import getargspec, formatargspec @wraps(func) def wrapper(self, *args, **kwargs): c = self.__class__.__name__ m = func.__name__ raise NotImplementedError('\'%s\' object does not implement the property \'%s\'' % (c, m)) return property(wrapper, wrapper, wrapper)
它可以用作
class AbstractBase(object): @not_implemented_method def test(self): pass @not_implemented_property def value(self): pass class Implementation(AbstractBase): value = None def __init__(self): self.value = 42 def test(self): return True
更好的方法是使用抽象基类 :
import abc class Foo(abc.ABC): @property @abc.abstractmethod def demo_attribute(self): raise NotImplementedError @abc.abstractmethod def demo_method(self): raise NotImplementedError class BadBar(Foo): pass class GoodBar(Foo): demo_attribute = 'yes' def demo_method(self): return self.demo_attribute bad_bar = BadBar() # TypeError: Can't instantiate abstract class BadBar \ # with abstract methods demo_attribute, demo_method good_bar = GoodBar() # OK
请注意,您应该仍然raise NotImplementedError
而不是类似pass
的东西,因为没有什么能够阻止inheritance类调用super().demo_method()
,并且如果抽象的demo_method
只是pass
,这将会失败。