Python Code:
######################################
class D(object):
def __init__(self):
self.default = 0.0
self.test = 20
self.test2 = 21
def __getattribute__(self, name):
try:
if name == 'test':
print ("__getattribute__ name = %s" % name)
return self.test #This will default call same function "__getattribute__", can fix by object
else:
print ("__getattribute__ name = %s" % name)
return object.__getattribute__(self, name)
except AttributeError:
print "getattribute error"
raise
def __getattr__(self, name):
print ("__getattr__ name = %s" % name)
print ("self.default=%s" % self.default)
return self.default
if __name__ == "__main__":
d = D()
#print d.test #This will caused recurison error because it call the same function, your getattribute
print d.test2
print d.ts #When "__getattribute__" raise error, it will call in "__getattr__".
######################################
输出:
>>>
__getattribute__ name = test2
21
__getattribute__ name = ts
getattribute error
__getattr__ name = ts
__getattribute__ name = default
self.default=0.0
__getattribute__ name = default
0.0
######################################
1. 任何调用类的属性行为都将从"__getattribute__"开始调用。
2. 在"__getattribute__"中调用该函数自身属性,将会导致无限循环。应该借用object对象再调用其本身。
3. "__getattr__"将会在寻找不到合适的函数或者属性时作为默认被调用到。
Python doc:
__getattr__( self, name)
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name. This method should return the (computed) attribute value or raise an AttributeError exception.
Note that if the attribute is found through the normal mechanism, __getattr__() is not called. (This is an intentional asymmetry between __getattr__() and __setattr__().) This is done both for efficiency reasons and because otherwise __setattr__() would have no way to access other attributes of the instance. Note that at least for instance variables, you can fake total control by not inserting any values in the instance attribute dictionary (but instead inserting them in another object). See the __getattribute__() method below for a way to actually get total control in new-style classes.
object.__getattribute__(self, name)?
Called unconditionally to implement attribute accesses for instances of the class. If the class also defines __getattr__(), the latter will not be called unless __getattribute__() either calls it explicitly or raises an AttributeError. This method should return the (computed) attribute value or raise an AttributeError exception. In order to avoid infinite recursion in this method, its implementation should always call the base class method with the same name to access any attributes it needs, for example, object.__getattribute__(self, name).
4. 通常来说,如果脚本即包含"__getattribute__" ,又包含"__getattr__"的时候,是不会调用到"__getattr__"的,但从上面的例子可以看出,如果"__getattribute__"报错,同样会自动调用到"__getattr__"。