如何取消覆盖 __setattr__ 方法?
这个问题的目的是想弄清楚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