对于类中未定义/未实现的属性的Python“catch all”方法

时间:2013-04-26 02:09:02

标签: python

喜欢 Python的@property装饰系统。我喜欢您在致电aClassObect.attribute时可以运行自定义代码。特别是在设置属性时验证数据。但是,我想要的一件事,但我找不到,是一种在尝试设置不存在的属性时运行自定义代码的方法。例如,假设我有以下课程:

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

现在,如果我有myObj,这是类C的一个实例,并且我调用myObject.x = 42,它将运行相应的setter,这对于验证数据非常有用。但这并不能阻止某人调用myOjbect.b = 47,并且会很乐意创建一个名为b的新属性。设置新属性时是否有某种方法可以运行特殊代码?我有能力提出错误,说“错误,这个属性不存在”。

2 个答案:

答案 0 :(得分:9)

要详细说明Elazar的答案,您需要覆盖__setattr__魔术方法,并检查其中是否已存在该属性。如果没有,请提出异常。以下是您班级的样子:

def __setattr__(self, name, value):
    if not hasattr(self, name): # would this create a new attribute?
        raise AttributeError("Creating new attributes is not allowed!")
    super(C, self).__setattr__(name, value)

如果您想处理对不存在的属性的请求,也可以覆盖__getattr____getattribute__,但对于您所描述的特定问题,这可能不是必需的。

请注意,由于删除操作,我上面显示的__setattr__方法不能完全与您当前的属性完美匹配。如果您删除myObj.x,之后如果您稍后尝试访问x,则getter会引发异常。这意味着hasattr在检查False是否为现有属性时会返回x,因此我的__getattr__将不允许您重新创建它。如果您确实需要能够删除(并重新创建)特定属性,则需要更复杂的__setattr__实现(它可以在类中检查具有所需名称的属性,而不仅仅是依赖于{ {1}})。

答案 1 :(得分:8)

覆盖__getattr____setattr__