python笔记61

前言

object 类里面有个 __getattribute__ 方法,作用是类实例化调用属性和方法的时候都会调用一次,返回该类的属性。
如果调用的属性没有,会抛出 AttributeError 异常。如果属性查找(attribute lookup)在实例以及对应的类中(通过__dict__)失败, 那么会调用到类的__getattr__方法。

__getattribute__方法

A类在调用自身属性的时候,是不会触发__getattribute__方法。
只有在调用A()实例属性或方法的时候,才会触发__getattribute__方法

# 作者-上海悠悠 QQ交流群:717225969 
# blog地址 https://www.cnblogs.com/yoyoketang/

class A(object):

    count = 0

    def __init__(self):
        self.name = "yoyo"
        self.age = 18

    def start(self):
        print("start1111111")

    def __getattribute__(self, item):
        """属性拦截器"""
        print("调用了A类的属性:", item)
        return object.__getattribute__(self, item)

a = A()
# A()实例对象属性会调用__getattribute__
print(a.count)
print(a.age)
print(a.name)
print(a.start())

如果A类属性(__dict__)没查找到,并且实例属性和方法也没找到,此时会抛出 AttributeError 异常

a = A()
print(a.weight)  # 找不到属性

运行结果

调用了A类的属性: weight
Traceback (most recent call last):
  File "demo/aaa.py", line 27, in <module>
    print(a.weight)  # 找不到属性
  File "demo/aaa.py", line 18, in __getattribute__
    return object.__getattribute__(self, item)
AttributeError: 'A' object has no attribute 'weight'

__getattr__方法

如果属性查找(attribute lookup)在实例以及对应的类中(通过__dict__)失败, 那么会调用到类的__getattr__方法。

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

class A(object):

    count = 0

    def __init__(self):
        self.name = "yoyo"
        self.age = 18

    def start(self):
        print("start1111111")

    def __getattribute__(self, item):
        """属性拦截器"""
        print("调用了A类的属性:", item)
        return object.__getattribute__(self, item)

    def __getattr__(self, item):
        """属性找不到会执行这个方法"""
        print("找不到该属性:%s" % item)
        return 'not found'


a = A()
# A()实例对象属性会调用__getattribute__
print(a.count)
print(a.age)
print(a.weight)

运行结果不会出现异常

调用了A类的属性: count
0
调用了A类的属性: age
18
调用了A类的属性: weight
找不到该属性:weight
not found

使用场景

网上有个很经典的使用示例,访问字典的key,像访问属性一样访问字典。
字典取值有2种方式,通过dict[key] 和dict.get(key)的方式取值。

a = {
    "name": "yoyo",
    "age": 18
}

# 字典访问
print(a["name"])
print(a.get("name"))

在其它语言里面,比如javascript里面可以把json当一个object对象,通过a.name,a.age这种点的方式就能直接取值了。
于是我们自己写一个类来实现这种方式

class ObjectDict(dict):
    def __init__(self, *args, **kwargs):
        super(ObjectDict, self).__init__(*args, **kwargs)

    def __getattr__(self, name):
        value = self[name]
        if isinstance(value, dict):
            value = ObjectDict(value)
        return value

if __name__ == '__main__':
    a = {
            "name": "yoyo",
            "age": 18
        }
    obj = ObjectDict(a)
    print(obj.name)
    print(obj.age)

也可以传多个值

if __name__ == '__main__':
    obj = ObjectDict(a={'age': 1, 'name': 'yoyo'}, d=True)
    print(obj.a)
    print(obj.a.name)
    print(obj.d)

dict嵌套dict也可以通过.的方式取值

if __name__ == '__main__':
    obj = ObjectDict(a={'age': 1,
                        'name': 'yoyo',
                        'data': {'id': 11, 'tel': 12345678900}}, d=True)
    print(obj.a)
    print(obj.a.name)
    print(obj.a.data)
    print(obj.a.data.id)
    print(obj.a.data.tel)

运行结果

{'age': 1, 'name': 'yoyo', 'data': {'id': 11, 'tel': 12345678900}}
yoyo
{'id': 11, 'tel': 12345678900}
11
12345678900

参考资料https://www.cnblogs.com/xybaby/p/6280313.html

原文地址:https://www.cnblogs.com/yoyoketang/p/15160890.html