Python中属性的查找过程分析
2021/8/24 22:06:11
本文主要是介绍Python中属性的查找过程分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一. 预备知识
1) 类中实现了__get__(), __set__(), __delete__()中任意一个方法,就是一个属性描述符
2) 数据属性描述符: 至少实现__set__()和__get__()方法
3) 非数据属性描述符: 实现除__set__()以外的方法
4) 使用属性描述符后, 可以在为属性赋值时增加一些逻辑判断
5) 假设obj是实例化对象, 那么 obj.name 等价于 getattr(obj, "name")
二. 属性的查找过程分析
2.1 __getattribute__方法是访问属性的入口
直接说结论:
属性查找优先级: __getattribute__方法 > 实例属性
__getattribute__方法是所有属性调用的入口, 需要注意的是这个方法如果使用不当,会导致程序死循环
# -*- coding: utf-8 -*- class Person(object): def __init__(self): self.name = "chinablue" self.age = 18 def __getattribute__(self, item): print(f"调用了__getattribute__方法") if "age" == item: return 38 return object.__getattribute__(self, item) p = Person() print(p.__dict__) # 实例属性信息: {'name': 'chinablue'} print(p.name) # 实例中有name属性: chinablue print(p.age) # 实例中有age属性,但__getattribute__方法拦截并修改了age属性: 38 # print(p.job) # 如果实例对象访问的属性不存在,也会访问__getattribute__方法
2.2 类属性对属性查找的影响
直接说结论:
属性查找优先级: 实例属性 > 类属性
实例没有的属性,会去类属性中查找
# -*- coding: utf-8 -*- class Person(object): # age是类属性 age = 18 def __init__(self): # name是实例属性 self.name = "chinablue" p = Person() print(p.__dict__) # 实例属性信息: {'name': 'chinablue'} print({k: v for k, v in Person.__dict__.items() if not k.startswith("__")}) # 类的属性信息: {'age': 18} print(p.name) # 实例中有name属性: chinablue print(p.age) # 实例中没有age属性,类中有age属性: 18
2.3 __getattr__方法对属性查找的影响
直接说结论:
属性查找优先级: 实例属性 > 类属性 > __getattr__方法
如果实例访问的属性不存在,则会抛出AttributeError异常
如果实例中定义了__getattr__方法, 当实例访问的属性不存在时, 会去访问__getattr__方法
# -*- coding: utf-8 -*- class Person(object): def __init__(self): # name是实例属性 self.name = "chinablue" # 当实例对象找不到属性时,会来调用__getattr__方法 def __getattr__(self, item): return "djtest" p = Person() print(p.__dict__) # 实例属性信息: {'name': 'chinablue'} print(p.name) # 实例中有name属性: chinablue print(p.job) # 实例中没有job属性,会调用__getattr__函数: djtest
另外, 如果实例对象中同时存在__getattr__方法和__getattribute__方法, 代码如下:
# -*- coding: utf-8 -*- class Person(object): def __init__(self): ... def __getattribute__(self, item): print(f"调用了__getattribute__方法") return object.__getattribute__(self, item) def __getattr__(self, item): print(f"调用了__getattr__方法") raise AttributeError(f"{item}属性不存在") p = Person() print(p.name) # 实例中没有name属性,先调用__getattribute__方法, 再调用__getattr__方法View Code
2.4 非数据属性描述符对属性查找的影响
直接说结论:
属性查找优先级: 实例属性 > 非数据属性描述符 > __getattr__方法
非数据属性描述符的优先级与类属性相当
# -*- coding: utf-8 -*- class PersonName: def __get__(self, instance, owner): return "djtest" class PersonAge: def __get__(self, instance, owner): return 28 class Person(object): # age和name是非数据描述符 age = PersonAge() name = PersonName() def __init__(self): self.name = "chinablue" p = Person() print(p.__dict__) # 实例属性信息: {'name': 'chinablue'} print({k: v for k, v in Person.__dict__.items() if not k.startswith("__")}) # 类的属性信息: {'age': <PersonAge object>, 'name': <PersonName object>} print(p.name) # 实例中有name属性: chinablue print(p.age) # 实例中没有age属性,类中(非数据描述符中)有age属性: 28
2.5 数据属性描述符对属性查找的影响
直接说结论:
属性查找优先级: 数据属性描述符 > 实例属性
# -*- coding: utf-8 -*- class PersonName: def __get__(self, instance, owner): return "djtest" def __set__(self, instance, value): self.name = value class Person(object): # name是数据描述符 name = PersonName() def __init__(self): self.name = "chinablue" p = Person() print(p.__dict__) # 实例属性信息: {} print({k: v for k, v in Person.__dict__.items() if not k.startswith("__")}) # 类的属性信息: {'name': <__main__.PersonName object at 0x033709B0>} print(p.name) # 实例中有name属性: djtest
三. 本章小结
对象属性的查找优先级参考如下:
__getattribute__方法 > 数据属性描述符 > 实例属性 > 类属性 | 非数据属性描述符 > __getattr__方法
这篇关于Python中属性的查找过程分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-14获取参数学习:Python编程入门教程
- 2024-11-14Python编程基础入门
- 2024-11-14Python编程入门指南
- 2024-11-13Python基础教程
- 2024-11-12Python编程基础指南
- 2024-11-12Python基础编程教程
- 2024-11-08Python编程基础与实践示例
- 2024-11-07Python编程基础指南
- 2024-11-06Python编程基础入门指南
- 2024-11-06怎么使用python 计算两个GPS的距离功能-icode9专业技术文章分享