我知道在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。问题主要是学术性的,因为从程序设计的角度来看这样做可能不是一个好主意,但它仍然值得一个答案 - 尽管我搜索过,但我无法在任何地方找到它。 / p>
答案 0 :(得分:3)
它记录在Data model,“类实例”部分:
属性赋值和删除更新实例的字典, 从来没有班级的字典。 如果班级有
__setattr__()
或__delattr__()
方法,调用此方法而不是直接更新实例字典。
所以无论是旧式还是新式,这两个检查总是在类型上进行,而不是实例。
答案 1 :(得分:2)
请参阅Python文档的这一部分:Special method lookups for new-style classes
对于新式类,特殊方法的隐式调用仅保证在对象的类型上定义时才能正常工作,而不是在对象的实例字典中。
按照链接详细说明这背后的理由。我理解的基本思想是,需要一致地调用适用于实例对象和类型对象(例如__repr__
)的特殊方法,而不是有时需要显式参数,有时需要接收隐式参数。通过始终在对象类型上调用方法,我们知道总是传递一个显式参数 - 但副作用是绕过实例字典。