> For the complete documentation index, see [llms.txt](https://jablack-programs.gitbook.io/python-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jablack-programs.gitbook.io/python-notes/basic-syntax/temp.md).

# temp

首先来看看上述三个魔法方法的定义吧：

（1）\_\_getattr\_\_(self, item):

在访问对象的item属性的时候，如果对象并没有这个相应的属性，方法，那么将会调用这个方法来处理。。。这里要注意的时，假如一个对象叫fjs,  他有一个属性：fjs.name = "fjs"，那么在访问fjs.name的时候因为当前对象有这个属性，那么将不会调用\_\_getattr\_\_()方法，而是直接返回了拥有的name属性了

（2）\_\_setattr\_\_(self, item, value):

当试图对象的item特性赋值的时候将会被调用。。

（3）\_\_getattribute\_\_(self, item):

这个只有在新式类中才有的，对于对象的所有特性的访问，都将会调用这个方法来处理。。。可以理解为在\_\_getattr\_\_之前

嗯。。。有了这几个方法就可以干很多很多的事情了。。。例如拦截器啥的。。。动态代理啥的。。。很方便就能实现了。。。起码比用java实现类似的功能方便多啦。。。。

不过需要注意的时候，在重写这些方法的时候需要特别的小心，因为容易引起循环调用。。。。

这里先来举一个例子，用于实现拦截所有的特性访问，在访问的时候打log啥的：**\[python]** [view plain](https://blog.csdn.net/fjslovejhl/article/details/40683547#) [copy](https://blog.csdn.net/fjslovejhl/article/details/40683547#)

1. \# -\*- coding: utf-8 -\*- &#x20;
2. class Fjs(object): &#x20;
3. &#x20;   def \_\_init\_\_(self, name): &#x20;
4. &#x20;       self.name = name &#x20;
5.
6. &#x20;   def hello(self): &#x20;
7. &#x20;       print "said by : ", self.name &#x20;
8.
9. &#x20;   def \_\_getattribute\_\_(self, item): &#x20;
10. &#x20;       print "访问了特性：" + item &#x20;
11. &#x20;       return object.\_\_getattribute\_\_(self, item) &#x20;
12.
13.
14. fjs = Fjs("fjs") &#x20;
15. print fjs.name &#x20;
16. fjs.hello() &#x20;

上述代码的输出如下：**\[python]** [view plain](https://blog.csdn.net/fjslovejhl/article/details/40683547#) [copy](https://blog.csdn.net/fjslovejhl/article/details/40683547#)

1. 访问了特性：name &#x20;
2. fjs &#x20;
3. 访问了特性：hello &#x20;
4. said by :  访问了特性：name &#x20;
5. fjs &#x20;

很简单就实现了拦截的功能吧。。。而且这里可以知道\_\_getattribute\_\_方法拦截了属性和方法的访问。。这里也就是所谓的所有的特性的访问了。。不过要注意的是：\_\_getattribute\_\_只有在新式类中才能用的。。。

嗯。。接下来配合使用\_\_getattr\_\_和\_\_getattribute\_\_来实现一个非切入式的编程：**\[python]** [view plain](https://blog.csdn.net/fjslovejhl/article/details/40683547#) [copy](https://blog.csdn.net/fjslovejhl/article/details/40683547#)

1. \# -\*- coding: utf-8 -\*- &#x20;
2. class Fjs(object): &#x20;
3. &#x20;   def \_\_init\_\_(self, name): &#x20;
4. &#x20;       self.name = name &#x20;
5.
6. &#x20;   def hello(self): &#x20;
7. &#x20;       print "said by : ", self.name &#x20;
8.
9. &#x20;   def fjs(self, name): &#x20;
10. &#x20;       if name == self.name: &#x20;
11. &#x20;           print "yes" &#x20;
12. &#x20;       else: &#x20;
13. &#x20;           print "no" &#x20;
14.
15. class Wrap\_Fjs(object): &#x20;
16. &#x20;   def \_\_init\_\_(self, fjs): &#x20;
17. &#x20;       self.\_fjs = fjs &#x20;
18.
19. &#x20;   def \_\_getattr\_\_(self, item): &#x20;
20. &#x20;       if item == "hello": &#x20;
21. &#x20;           print "调用hello方法了" &#x20;
22. &#x20;       elif item == "fjs": &#x20;
23. &#x20;           print "调用fjs方法了" &#x20;
24. &#x20;       return getattr(self.\_fjs, item) &#x20;
25.
26. fjs = Wrap\_Fjs(Fjs("fjs")) &#x20;
27. fjs.hello() &#x20;
28. fjs.fjs("fjs") &#x20;

这里通过\_\_getattr\_\_方法，将所有的特性的访问都路由给了内部的fjs对象。。。。。。

最后，关于\_\_setattr\_\_()方法，这个就不细说了。。。不过他的使用还需要特别注意一些。。因为稍不注意就容易陷入循环调用了。。。。
