zoukankan      html  css  js  c++  java
  • Python __getattribute__ vs __getattr__

    # 例子在原来的基础上简化了一下,排除依赖和干扰,详细参见原项目
    class UrlGenerator(object):
        def __init__(self, root_url):
            self.url = root_url
    
        def __getattr__(self, item):
            if item == 'get' or item == 'post':
                print self.url
            return UrlGenerator('{}/{}'.format(self.url, item))
    
    
    url_gen = UrlGenerator('http://xxxx')
    url_gen.users.show.get
    
    >>> http://xxxx/users/show
    

    充分利用getattr会在没有查找到相应实例属性时被调用的特点,方便的通过链式调用生成对应的url,源代码中在碰到http method的时候返回一个
    可调用的对象更加的优雅,链式的操作不仅优雅而且还能很好的说明调用的接口的意义(restful的接口啦)。

    既然能通过定制类的getattr自定义方法来实现一些优雅的功能,自然我们也要对它有一些了解,包括和它相似的自定义方法getattribute

    1. 用作实例属性的获取和拦截

    当访问某个实例属性时, getattribute会被无条件调用,如未实现自己的getattr方法,会抛出AttributeError提示找不到这个属性,如果自定义了自己getattr方法的话,方法会在这种找不到属性的情况下被调用,比如上面的例子中的情况。所以在找不到属性的情况下通过实现自定义的getattr方法来实现一些功能是一个不错的方式,因为它不会像getattribute方法每次都会调用可能会影响一些正常情况下的属性访问:

    class Test(object):
        def __init__(self, p):
            self.p = p
    
        def __getattr__(self, item):
            return 'default'
    
    t = Test('p1')
    print t.p
    print t.p2
    
    >>> p1
    >>> default
    

    2. 自定义getattribute的时候防止无限递归

    因为getattribute在访问属性的时候一直会被调用,自定义的getattribute方法里面同时需要返回相应的属性,通过self.__dict__取值会继续向下调用getattribute,造成循环调用:

    class AboutAttr(object):
        def __init__(self, name):
            self.name = name
    
        def __getattribute__(self, item):
            try:
                return super(AboutAttr, self).__getattribute__(item)
            except KeyError:
                return 'default'
    

    这里通过调用绑定的super对象来获取队形的属性,对新式类来说其实和object.__getattribute__(self, item)一样的道理:

    • 默认情况下自定义的类会从object继承getattribute方法,对于属性的查找是完全能用的
    • getattribute的实现感觉还是挺抽象化的,只需要绑定相应的实例对象和要查找的属性名称就行

    3.同时覆盖掉getattribute和getattr的时候,在getattribute中需要模仿原本的行为抛出AttributeError或者手动调用getattr

    class AboutAttr(object):
        def __init__(self, name):
            self.name = name
    
        def __getattribute__(self, item):
            try:
                return super(AboutAttr, self).__getattribute__(item)
            except KeyError:
                return 'default'
            except AttributeError as ex:
                print ex
    
        def __getattr__(self, item):
            return 'default'
    
    at = AboutAttr('test')
    print at.name
    print at.not_exised
    
    >>>test
    >>>'AboutAttr' object has no attribute 'not_exised'
    >>>None
    

    上面例子里面的getattr方法根本不会被调用,因为原本的AttributeError被我们自行处理并未抛出,也没有手动调用getattr,所以访问not_existed的结果是None而不是default.

      

      

      

      

  • 相关阅读:
    Kinect 开发 —— 硬件设备解剖
    Kinect 开发 —— 引言
    (转)OpenCV 基本知识框架
    OpenCV —— 摄像机模型与标定
    OpenCV —— 跟踪与运动
    OpenCV —— 图像局部与分割(二)
    OpenCV —— 图像局部与部分分割(一)
    OpenCV —— 轮廓
    OpenCV —— 直方图与匹配
    OpenCV —— 图像变换
  • 原文地址:https://www.cnblogs.com/morgana/p/8688971.html
Copyright © 2011-2022 走看看