如何取消覆盖 __setattr__ 方法?

0 投票
1 回答
1217 浏览
提问于 2025-04-17 12:31

这个问题的目的是想弄清楚Python中的内置函数到底有多“内置”。

如果我重写了setattr这个方法,我该怎么把它恢复呢?比如,我有一个叫“Working”的类,代码是这样的:

class WorkingSetAttr:
    def a(self): return 'a'
    def b(self): return 'b'

还有一个叫“NonWorking”的类,代码是这样的:

class NonWorkingSetAttr: 
    def a(self): return 'a'
    def b(self): return 'b'
    def __setattr__(self,a,b): pass

现在我创建了两个对象w和n,然后运行以下代码:

w = WorkingSetAttr()
setattr(w,'a',w.b)
print "w.a = %s, w.b = %s" % (w.a(), w.b())

n = NonWorkingSetAttr()
setattr(n, 'a', n.b)
print "n.a = %s, n.b = %s" % (n.a(), n.b())

输出结果是:

w.a = b, w.b = b
n.a = a, n.b = b

注意,n.a应该打印“b”,但它却打印了“a”,因为setattr并没有改变这个属性。

问题是:我应该怎么修改对象n,让它的表现和对象w一样。注意,我说的是对象,不是类。

1 个回答

1

你可以直接把类里面的自定义 __setattr__ 去掉。

>>> n = NonWorkingSetAttr()
>>> setattr(n, 'a', n.b)
>>> print("n.a = %s, n.b = %s" % (n.a(), n.b()))
n.a = a, n.b = b
>>> 
>>> del NonWorkingSetAttr.__setattr__
>>>
>>> setattr(n, 'a', n.b)
>>> print("n.a = %s, n.b = %s" % (n.a(), n.b()))
n.a = b, n.b = b

要注意,这样做是修改了 ,而不是修改对象。你(几乎肯定)不想去改对象本身,因为那样的话,你的对象看起来应该是 NonWorkingSetAttr,但实际上却变成了一种你不太明白的动态东西。

如果你不能修改这个类,你可以创建一个子类,然后用 object__setattr__ 来重新覆盖它:

>>> class FixedNonWorkingSetAttr(NonWorkingSetAttr):
...     __setattr__ = object.__setattr__
... 
>>> n = FixedNonWorkingSetAttr()
>>> setattr(n, 'a', n.b)
>>> print("n.a = %s, n.b = %s" % (n.a(), n.b()))
n.a = b, n.b = b
>>> isinstance(n, NonWorkingSetAttr)
True

撰写回答