如何在Python3中正确调用__setattr __()作为类的一部分?

时间:2016-01-26 10:00:32

标签: python python-3.x setattr

我想在设置对象属性时调用函数:

class MyClass():
    myattrib = None

    def __setattr__(self, prop, val):
        self.myattrib = val
        print("setting myattrib")

x = MyClass()
x.myattrib = "something"

问题是,这会产生无限递归。

想法是在设置成员变量时调用函数(并实际设置该成员变量),但同时运行额外的代码(在上面的示例中使用print()语句展示)。 / p>

另一种显而易见的方法是使用set_attrib()函数,这在Java中很常见,但我想用 pythonic 方式,并直接设置属性,但同时运行额外的代码。

2 个答案:

答案 0 :(得分:4)

通过super()

调用基本版本
class MyClass(object):
    myattrib = None

    def __setattr__(self, prop, val):
        super().__setattr__('myattrib', val)
        print("setting myattrib")

你可能想要忽略prop这里的参数,它不一定是'myattrib'被设置。

但是,请考虑使用属性而不是拦截所有属性设置:

class MyClass(object):
    _myattrib = None

    @property:
    def myattrib(self):
        return self._myattrib

    @myattrib.setter
    def myattrib(self, val):
        self._myattrib = val
        print("setting myattrib")

我添加了object作为基类;这是Python 3中的默认值,但要求super()property对象在Python 2中工作。

答案 1 :(得分:3)

如果您想在设置任何属性时执行特定操作,请使用__setattr__并使用super调用继承的版本进行实际分配:

def __setattr__(self, prop, val):
    super().__setattr__(prop, val)
    print("setting {} to {!r}".format(prop, val)

如果您只想为一个属性(不是所有属性)执行特殊操作,则应该使用property代替:

class MyClass():
    @property
    def some_attribute(self):
        return self._val

    @some_attribute.setter
    def some_attribute(self, value):
        self._val = value
        print("set some_attribute to {!r}".format(value))