分享

python笔记61 - __getattr__ 属性查找学习与使用

 上海悠悠 2021-08-20

前言

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

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多