5

我知道在 Python 中可以在运行时向类添加方法:

class Test:
    def __init__(self):
        self.a=5

test=Test()

import types
def foo(self):
    print self.a
test.foo = types.MethodType(foo, test)
test.foo() #prints 5

而且我也知道可以覆盖类定义中的默认setattr :

class Test:
    def __init__(self):
        self.a=5
    def __setattr__(self,name,value):
        print "Possibility disabled for the sake of this test"

test=Test() #prints the message from the custom method called inside __init__

但是,似乎无法在运行时覆盖setattr

class Test:
    def __init__(self):
        self.a=5

test=Test()

import types
def __setattr__(self,name,value):
    print "Possibility disabled for the sake of this test"
test.__setattr__ = types.MethodType(__setattr__, test)
test.a=10 #does the assignment instead of calling the custom method

在最后两种情况下, dir(test) 还报告方法setattr。但是,虽然在第一种情况下它可以正常工作,但在第二种情况下却不能。请注意,我也可以显式调用它,在这种情况下它可以工作。似乎是这样,虽然方法已定义,但尚未正确映射以覆盖默认分配方法。我错过了什么吗?

顺便说一句,我正在使用 Python 2.7。这个问题主要是学术性的,因为从程序设计的角度来看,做这样的事情可能不是一个好主意,但它仍然值得一个答案——尽管我进行了搜索,但我无法在任何地方找到它的文档。

4

2 回答 2

3

它记录在数据模型,“类实例”部分:

属性分配和删除会更新实例的字典,而不是类的字典。如果类__setattr__()or __delattr__()方法,则调用此方法而不是直接更新实例字典。

因此,无论是旧式还是新式,这两个检查总是针对类型,而不是实例。

于 2012-11-16T00:24:04.147 回答
2

请参阅 Python 文档的这一部分:新样式类的特殊方法查找

对于新式类,特殊方法的隐式调用只有在对象的 type 上定义时才能保证正常工作,而不是在对象的实例字典中。

按照链接详细说明其背后的基本原理。据我了解,基本思想是适用于实例对象和类型对象(例如__repr__)的特殊方法需要一致地调用,而不是有时需要显式参数,有时需要接收隐式参数。通过总是调用对象类型的方法,我们知道总是传递一个显式参数 - 但副作用是实例字典被绕过。

于 2012-11-16T00:12:45.613 回答