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

发布于 2021-01-29 14:10:39

我想在类中定义一些常量,这些常量将在类实例(派生的类)中定义-
如果未在子类中重新定义此变量,如何发出错误信号?我想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 = ?
关注者
0
被浏览
105
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    首先,最明显的是不要在父类中做任何事情。然后,在阅读时,您只会得到一个属性错误:

    AttributeError: Child instance has no attribute 'abstract_variable'
    

    或者在父类中,您可以在每个子类中都有一个使用getter和setterproperty引发NotImplementedError
    覆盖它的property。或在子类中将值设置为None在类主体中…


    但是,如果要提高NotImplementedError,则可以创建一个 非数据 描述符(即, 没有
    描述符类 ,始终具有)。这使您可以在子类中设置值。
    ____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


    但是,等等,我们可以使其更加神奇:描述符可以找出从 哪个 属性访问它:

    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会引发异常提示信息:

    NotImplementedError: <__main__.Child object at 0x7f7c7a5dd860> does not
    have the attribute 'variable' (abstract from class 'Parent')
    

    Child.variable

    NotImplementedError: <class '__main__.Child'> does not have the 
    attribute 'variable' (abstract from class 'Parent')
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看