zoukankan      html  css  js  c++  java
  • python __getattr__ & __getattribute__ 学习

    实例属性的获取和拦截, 仅对实例属性(instance, variable)有效, 非类属性

    getattr: 适用于未定义的属性, 即该属性在实例中以及对应的类的基类以及祖先类中都不存在
    1. 动态处理事先未定义的属性, 可更好的实现数据隐藏, 当调用dir(obj)时只会显示初始化定义的正常的属性和方法
    getattribute: 对于所有属性的访问都会调用该方法, 当属性不存在时会报错
    1. 覆盖该方法之后,任何属性的访问都会调用用户自定义的__getattribute__()方法, 性能上会有所损耗.

    1. 当两个方法同步被重写, 要么在__getattribute__()中显示调用, 要么是触发AttributeError异常时, getattr()才会被调用
    2. 要避免无穷递归调用
    3. 如果访问未定义属性, 且在__getattr__中未跑出AttributeError异常或者显性的返回一个值, 则会返回None

    参考: 编写高质量代码:改善Python程序的91个建议

    class Attribute(object):
        def __init__(self, name):
            self.name = name
    
        def __getattribute__(self, key):
            try:
                print('calling __getattribute__.{key}'.format(key=key))
                # 调用超类
                return super(Attribute, self).__getattribute__(key)
                # return object.__getattribute__(self, key)
            except KeyError:
                return 'default'
            except AttributeError as ex:  # 捕获了该异常就不用调用__getattr__
                print(ex)
    
        def __getattr__(self, key):
            # 什么时候被调用:
            # 1.当属性不在实例以及基类和祖先类的__dict__
            # 2. 当触发AtrributeError异常时(不仅仅是__getattribute__()引发的 AttributeError),porperty中定义的get()方法也会抛出异常
            print('calling __getattr__.{key}'.format(key=key))
            # return 'default'
    

    测试 property, getattribute, __getattr__调用顺序

    class A(object):
        _c = 'test'
        def __init__(self):
            self.x = None
    
        @property
        def a(self):
            print('using property to access attribute')
            if self.x is None:
                print('return value')
                return 'a'
            else:
                print('error occured')
                raise AttributeError
    
        @a.setter
        def a(self, value):
            self.x = value
    
        def __getattribute__(self, name):
            print('using __getattribute__ to access attribute')
            return object.__getattribute__(self, name)
    
        def __getattr__(self, name):
            print('using __getattr__ to access attribute')
            print('attribute name: ', name)
            return 'b'
    
    
    
    if __name__ == '__main__':
        a = Attribute('atest')
        print(a.name)
        print(a.test)
    
        # 测试 property, __getattribute__, __getattr__调用顺序
        # b = A()
        # print(b.a)
        # print('-'*50)
        # b.a = 10
        # print(b.a)
        # print('-'*50)
        # print(A._c)
    

    defaultdict 和 魔法方法__missing__()

    dict中并不存在__missing__()方法, 需要派生子类并重写__missing__()方法

    # python 2.5 之前默认要自己重写__missing__方法
    # python3以后 __missing__(key) called by __getitem__ for missing key;
    class DefaultDict(dict):
        def __init__(self, default_factory, *args, **kwargs):
            super(DefaultDict, self).__init__(*args, **kwargs)    
            self.default_factory = default_factory
        
        def __getitem__(self, key):
            try:
                return dict.__getitem__(self, key)
            except KeyError:
                return self.__missing__(key)    
    
        def __missing__(self, key):
            self[key] = value = self.default_factory()
            return value
    
    
  • 相关阅读:
    今年要读的书
    java多线程
    json-lib 使用教程
    tomcat原理
    静态long类型常量serialVersionUID的作用
    使用junit4测试Spring
    MySQL各版本的区别
    spring mvc 下载安装
    hibernate、struts、spring mvc的作用
    【面试】hibernate n+1问题
  • 原文地址:https://www.cnblogs.com/panlq/p/11857486.html
Copyright © 2011-2022 走看看