zoukankan      html  css  js  c++  java
  • __getattribute__

    我们根据一个小栗子,来更好的理解 __getattribute__的用法:

    -- python2:

    class Tree(object):  #继承object
        def __init__(self,name):
            self.name = name
            self.cate = 'plant'
        def __getattribute__(self, item):
            print 'haha'
            return object.__getattribute__(self,item)
    
    a = Tree('大树')
    print a.name

    结果:

    haha
    大树
    class Tree():  #不继承object
        def __init__(self,name):
            self.name = name
            self.cate = 'plant'
        def __getattribute__(self, item):
            print 'haha'
            return object.__getattribute__(self,item)
    
    a = Tree('大树')
    print a.name

    结果:

    大树

    为什么会出现这个结果呢?

    __getattribute__是属性拦截器, 就是当这个类的属性被访问时, 会自动调用类的 __getattribute__方法. 即在上面的代码中, 当我们调用实例对象a的name属性时, 不会直接打印, 而是把属性名name作为实参, 传进__getattribute__方法中, 经过一系列操作后, 再把name的值返回. 并且还能看出, 只有继承object 时, 属性拦截器才会发挥作用, 所以, python中只要定义了继承object的类( python3默认继承object ), 就默认存在属性拦截器. 所以我们可以自己改写 __getattribute__方法来实现相关功能, 比如查看权限, 打印log日志等.

    另外, 在使用__getattribute__方法时要注意: 

    不能在__getattribute__中自调用对象的属性, 会造成死循环.

    class Tree(object):
        def __init__(self, name):
            self.name = name
            self.cate = "plant"
    
        def __getattribute__(self, *args, **kwargs):
            if args[0] == 'name':
                print("log 大树")
                return "我爱大树"
            else:
                return self.call_wind()
        def call_wind(self):
            return '刮大风,下大雨'
    
    
    aa = Tree("大树")
    print(aa.name)
    print(aa.cate)

    结果:

    log 大树
    我爱大树
    Traceback (most recent call last):
      File "D:/test.py", line 18, in <module>
        print(aa.cate)
      File "D:/test.py", line 11, in __getattribute__
        return self.call_wind()
      File "D:/test.py", line 11, in __getattribute__
        return self.call_wind()
      File "D:/test.py", line 11, in __getattribute__
        return self.call_wind()
      [Previous line repeated 995 more times]
      File "D:/test.py", line 7, in __getattribute__
        if args[0] == 'name':
    RecursionError: maximum recursion depth exceeded in comparison

    结果分析: 当执行 aa.cate 时, 先调用__getattribute__方法,经过判断后, 返回 self.call_wind(), 但是当调用 aa的call_wind() 属性时, 又要去调用 __getattribute__方法, 反反复复, 最终超过最大递归限度.

    __getattribute__ 和 __getattr__ 的最大差异在于:

    1. 无论调用对象的什么属性, 包括不存在的属性, 都会首先调用 __getattribute__方法;

    2. 只有调用的对象属性不存在时, 才会调用 __getattr__方法.

  • 相关阅读:
    客户端session与服务端session
    对session和cookie的一些理解
    Servlet生命周期与工作原理
    Linux命令行编辑快捷键
    含有GROUP BY子句的查询中如何显示COUNT()为0的成果(分享)
    设计模式学习——准备(UML类图)
    find()方法
    js中的动态效果
    动态添加,移除,查找css属性的方法
    VUE中的require ( )
  • 原文地址:https://www.cnblogs.com/yaraning/p/11796489.html
Copyright © 2011-2022 走看看