Python:忽略父__setattr__

时间:2016-12-23 09:18:52

标签: python

拥有以下代码:

class Parent():
    def __init__(self):
        pass

    def __setattr__(self, name, value):
        raise RuntimeError()


class Child(Parent):
    def __init__(self):
        super().__init__()
        self.y = 2


if __name__ == '__main__':
    print(Child().y)

以下条件/假设:

  • Parent在其__setattr__实现中执行了一些操作,使Child在设置新的类属性时引发异常。
  • Parent源代码无法修改(可能是猴子修补,但它是外部依赖项)。

有没有办法解决这个问题?在设置Parent之前,我可以“废弃”__setattr__的{​​{1}}实施吗?我可以在y中重新实现此方法,以使其按预期工作吗?

3 个答案:

答案 0 :(得分:2)

您可以通过在MRO中查找 next __setattr__方法来绕过该方法。告诉super() 过去 Parent

class Child(Parent):
    def __init__(self):
        super().__init__()
        self.y = 2

    def __setattr__(self, name, value):
        # skip Parent.__setattr__
        super(Parent, self).__setattr__(name, value)

请注意,您通常使用与super()中当前不同的类;这是一个适当的例外,但请在您的生产代码中包含注释,以解释您为什么这样做。

也可以使用object.__setattr__(self, name, value),但前提是Parent直接来自object,而不是来自同时实施__setattr__的其他类。使用super()会在继承树中找到 next __setattr__实现。

演示:

>>> class Parent():
...     def __init__(self):
...         pass
...     def __setattr__(self, name, value):
...         raise RuntimeError()
...
>>> class Child(Parent):
...     def __init__(self):
...         super().__init__()
...         self.y = 2
...     def __setattr__(self, name, value):
...         # skip Parent.__setattr__
...         super(Parent, self).__setattr__(name, value)
...
>>> Child().y
2

答案 1 :(得分:1)

您可以调用基础__setattr__

object.__setattr__(self, 'y', 2)

请注意,这完全绕过Parent的{​​{1}},因此这样做可能会破坏__setattr__中的各种不变量。

答案 2 :(得分:0)

__setattr__中添加Child方法,您可以忽略Parent中的方法:

class Child(Parent):
    ...
    def __setattr__(self, name, value):
        # do whatever you want;