Python中的__getattr__()与__getattribute__()
昨天各大IT网站头版都是XXX黑客自杀的消息,虽然我不认识,但是后来发现这个人是reddit的联合创始人,而且还开发了web.py框架,web.py虽然没用过,但是大名还是听过的,所以今天就去看了下web.py的源码。。。
主要关注了template那一块,发现web.py的template的一种使用方式是这样的:
render = web.template.render('templates') print render.foo()
其中templates是放模板的文件夹,而foo是文件夹中的一个文件名,如foo.html。
就是这里太神奇了!其他语言中从来没见,python是怎么办到的?!
后来发现Render类中有个__getattr__函数:
1 def __getattr__(self, name): 2 t = self._template(name) 3 if self._base and isinstance(t, Template): 4 def template(*a, **kw): 5 return self._base(t(*a, **kw)) 6 return template 7 else: 8 return self._template(name)
接着去查了下python的文档,如是说:
object.__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.
bingo!原来是当调用类的成员时找不到的情况下会调用__getattr__。
再往下看,还发现有个__getattribute__:
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.
原来当access类的成员的时候__getattribute__将会无条件调用。如果失败了,或者主动调用,__getattr__才会被调用。

浙公网安备 33010602011771号