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

标签 python

我想在类中定义一些常量,这些常量将在类实例(派生类)中定义——如果这个变量没有在子类中重新定义,如何发出错误信号?我想在第一次阅读时引发 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'

或者在父类中你可以有一个 property 引发 NotImplementedError property 覆盖它每个子类中都有 getter 和 setter;或者在子类中将值设置为类主体中的 None...


但是,如果您想引发 NotImplementedError,您可以制作一个非数据 描述符(即 descriptor class 没有 __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

property 无法像使用我的 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')

关于python - 如何在 Python 中定义惰性变量,这将引发抽象代码框架的 NotImplementedError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32536176/

相关文章:

python - 如何在保存后停止 VScode 还原我的更改

Python 多处理 : is it possible to have a pool inside of a pool?

Python 3.x - 使用代表整数的符号创建垂直列表

python - 我导入的 .txt 表与标题没有正确对齐 (Python)

javascript - 将基于 JIT 的 lang 编译为 Webassembly

python - 使用 paramiko 进行 x11 转发

python - 是否有 Python 库来处理 OWL?

python - 用 python sleep 和醒来

python - 如何扫描 pandas 行中的第一个非零值并使用数字创建新列

python - 如何在不使用 OpenCV 的情况下从网络摄像头获取图像?