我想在类中定义一些常量,这些常量将在类实例(派生的类)中定义- 如果未在子类中重新定义此变量,如何发出错误信号?我想NotImplementedError读一读。
NotImplementedError
class Parent(object): abstract_variable = ? # I want achieve same behavior for variable def abstract_function(self): raise NotImplementedError() class Child(Parent): def __init__(): # should throw NotImplementedError() on read print self.abstract_variable
可以一行完成吗?
abstract_variable = ?
首先,最明显的是不要在父类中做任何事情。然后,在阅读时,您只会得到一个属性错误:
AttributeError: Child instance has no attribute 'abstract_variable'
或者在父类中,您可以在每个子类中都有一个使用getter和setterproperty引发NotImplementedError 并 覆盖它的property。或在子类中将值设置为None在类主体中…
property
None
但是,如果要提高NotImplementedError,则可以创建一个 非数据 描述符(即, 没有 的描述符类 ,始终具有)。这使您可以在子类中设置值。 ____set__``property``__set__
__set__``property``__set__
最简单的方法是
class abstract_attribute(object): def __get__(self, obj, type): raise NotImplementedError("This attribute was not set in a subclass")
你像这样使用它
class Parent(object): variable = abstract_attribute() class Child(Parent): def __init__(self): try: print(self.variable) except Exception as e: print("Got error %s" % e) self.variable = 42 print(self.variable) Child()
哪个输出
Got error This attribute was not set in a subclass 42
Aproperty不能像my那样容易地设置值abstract_attribute。
abstract_attribute
但是,等等,我们可以使其更加神奇:描述符可以找出从 哪个 属性访问它:
class abstract_attribute(object): def __get__(self, obj, type): # Now we will iterate over the names on the class, # and all its superclasses, and try to find the attribute # name for this descriptor # traverse the parents in the method resolution order for cls in type.__mro__: # for each cls thus, see what attributes they set for name, value in cls.__dict__.items(): # we found ourselves here if value is self: # if the property gets accessed as Child.variable, # obj will be done. For this case # If accessed as a_child.variable, the class Child is # in the type, and a_child in the obj. this_obj = obj if obj else type raise NotImplementedError( "%r does not have the attribute %r " "(abstract from class %r)" % (this_obj, name, cls.__name__)) # we did not find a match, should be rare, but prepare for it raise NotImplementedError( "%s does not set the abstract attribute <unknown>", type.__name__)
使用此代码,访问self.variable会引发异常提示信息:
self.variable
NotImplementedError: <__main__.Child object at 0x7f7c7a5dd860> does not have the attribute 'variable' (abstract from class 'Parent')
并Child.variable给
Child.variable
NotImplementedError: <class '__main__.Child'> does not have the attribute 'variable' (abstract from class 'Parent')