如何在Python中定义将引发抽象代码框架NotImplementedError的惰性变量?

如何在Python中定义将引发抽象代码框架NotImplementedError的惰性变量?,python,Python,我想在类中定义一些常量,这些常量将在类实例(派生类)中定义-如果这些变量未在子类中重新定义,如何发出错误信号?我想在第一次阅读时提出NotImplementedError class Parent(object): abstract_variable = ? # I want achieve same behavior for variable def abstract_function(self): raise NotImplementedError() cla

我想在类中定义一些常量,这些常量将在类实例(派生类)中定义-如果这些变量未在子类中重新定义,如何发出错误信号?我想在第一次阅读时提出
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 = ?
请看他的答案,他提供了一个更好的答案

将该函数用作装饰器

class Parent(object):
   @property
   def abstract_variable(self):
     raise NotImplementedError()

获取
实例.abstract_变量
将抛出一个
NotImplementedError
首先,最清楚的是不要在父类中执行任何操作。 然后在读取时,您只会得到一个属性错误:

AttributeError: Child instance has no attribute 'abstract_variable'
或者在父类中,您可以有一个
属性
,该属性会引发
未实现错误
,并在每个子类中使用带有getter和setter的
属性
覆盖它;或者在子类中,在类主体中将值设置为
None


但是,如果要引发
未实现错误
,则可以创建非数据描述符(即,不带
\uuuuuu集
,属性始终具有
\uuu集
)。这允许您在子类中设置值

最直接的方法是

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
属性
无法像使用我的
抽象_属性
那样轻松设置值


但是,等等,我们可以让它更神奇:描述符可以找出访问它的属性:

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__)
Child.variable
给出

NotImplementedError: <class '__main__.Child'> does not have the 
attribute 'variable' (abstract from class 'Parent')
NotImplementedError:没有
属性“variable”(从类“Parent”抽象)

看看。您希望子类用类变量还是实例变量覆盖父类?也就是说,如果它做对了,孩子会是什么样子?看起来很有希望,我很快就会测试。看来这正是我们需要的。非常感谢您的回答,我将在第一次测试后接受这个问题。特别好的是多态性与mro与我经常使用太多。
NotImplementedError: <class '__main__.Child'> does not have the 
attribute 'variable' (abstract from class 'Parent')