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

J-b*_*bob 13 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
Run Code Online (Sandbox Code Playgroud)

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

Blc*_*ght 10

要详细说明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)
Run Code Online (Sandbox Code Playgroud)

它也可以覆盖__getattr__或者__getattribute__如果你想处理不存在的属性的请求,但是对于你所描述的特定问题,这可能不是必需的.

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


Ela*_*zar 9

覆盖__getattr____setattr__.