当前位置: 首页 > news >正文

__getattribute__ python __getattribute__炸裂真相:Python属性查找竟藏着这种魔鬼逻辑

全新采用了新式类, 摒弃了旧式类, 身为新式类的一项特性有着极为奇妙的功效。查阅一些博客以及文章之时, 察觉到欲要透彻领会和的差异, 事实上得领会中属性的查找次序、描述器()、、、等相关知识。

首要的是要明确指出, 要是存在一个类, 其仅仅定义了方法,那么这种类就被称作non - data(非资料描述器), 要是这个类既把某个东西和另一个东西都定义了, 那么它就被称作data(资料描述器), 具体的情况能够在我的那里看到, 这便于理解。接下来进行实例属性查找顺序的介绍。假定t = T(), t.at的查找顺序是像下面这样的:。

1、如果是自动产生的属性,返回,否则进行第2步

2、要是“at”在T或者它的父类以及祖先类里面出现了(表示“at”是类属性, 不是仅属于t的实例属性), 而且at是一个data, 那么就优先调用它的方法。倘若是非data或者不存在该属性情况, 那就进行第2步。

3、找寻一下实例t之中是不是存在at属性, 要是有的话就予以返回, 要是没有的话那就进入到第3步。

4、查找t的父类之中, 是否存在at属性;还要查找t的祖先类之中以及别处, 是否存在at属性;要是没有at属性, 那么就执行第4步;要是有at属性, 那么就执行如下步骤:

4.1处的at属于一个non - data , 去调用它的方法 , 要是并非如此那就去执行3.2。

​ 4.2 返回'at'

5、如果实例t的父类中有方法,则调用该方法,没有则抛出。

需留意, 每当类或者实例对属性进行调用之际, 都会被毫无条件地在最起初的时候予以调用。下面的代码篇幅稍长, 烦请耐心去查看。

class Descriptor: # 定义描述器的类 def __get__(self, instance, owner): # get方法用于返回实例的a属性 print('3 get called,', 'instance is', instance, ',owner is', owner) return instance.a def __set__(self, instance, value): # set方法用于修改实例的a属性 print('4 set called,', 'instance is', instance, ',value is', value) instance.a = value**2 def __getattribute__(self, item): print('5 Des getattribute called, item is %s' % item) class NotDescriptor: # 定义non-data descriptor def __get__(self, instance, owner): print('6 get called,', 'instance is', instance, ',owner is', owner) return instance.a - 100 class T: desc = Descriptor() # 类属性,一个资料描述器 data descriptor Not_Desc = NotDescriptor() # 类属性,一个非资料描述器 non-data descriptor def __init__(self): self.a = 123 self.not_desc = 'instance not_desc' def func(self): return 'T func' def __getattribute__(self, item): print('1 getattribute called, item is ', item) return object.__getattribute__(self, item) def __getattr__(self, item): print('2 getattr called, item is', item) raise AttributeError('NO such attr %s' % item)

下面的这些测试, 全都运用上方的那代码, 每一回的输出操作, 都已进行过重置, 目的是防止出现混淆。

1 getattribute called, item is func T func # 实例的函数 1 getattribute called, item is a 123 # 实例的属性 ================================================== 4 set called, instance is <__main__.T object at 0x000001E55B630240> ,value is 2 # set方法前不调用getattribute。instance是拥有该描述器类的一个实例。value是要设置的值。 ================================================== 1 getattribute called, item is desc 3 get called, instance is <__main__.T object at 0x000001E55B630240> ,owner is # get方法前还是优先调用getattribute,instance是拥有该描述器对象的一个实例。owner是拥有者本身 1 getattribute called, item is a t.a = 4 # 2**2 = 4

可以看到, 在调用实例的属性以及方法的时候, 都会毫无条件地率先调用方法, 然而set方法是不会被调用的。此外, 代码借助描述器的get方法以及set方法, 实际上已然达成了类似于@的运用情况。当然了, 装饰器实在是基于描述器而得以实现的, 要是对装饰器并不明白的话, 是能够去查看我的。

下面继续使用上方代码验证、非描述器的执行顺序。

t = T() print(t.not_desc) --------结果如下------ 1 getattribute called, item is not_desc instance not_desc

回想前面所提及的属性查找顺序, 在类当中被找到了, 然而并非如此, 所以执行第二步, 于实例的里面发现了该属性, 进而返回。

t = T() print(t.Not_Desc) --------结果如下------ 1 getattribute called, item is Not_Desc 6 get called, instance is <__main__.T object at 0x0000017F70A006A0> ,owner is # 这里是NonDataDescriptor中的get方法 1 getattribute called, item is a 23 # a的初始值为123 由get方法返回的是123-100=23

依据我们先前提及的顺序, 属性于类之中被找到, 然而并非data , 且未在实例的dict里找到, 于是进展到了4.1步骤, 发觉它是一个non-data , 随后便执行了其中的get方法。

t = T() print(t.bbbbbb) # T类中没有定义该属性 ------结果如下---------- 1 getattribute called, item is bbbbbb 2 getattr called, item is bbbbbb Traceback (most recent call last): File "C:/省略/.py", line 40, in print(t.bbbbbb) File "C:C:/省略/.py.py", line 36, in __getattr__ raise AttributeError('NO such attr %s' % item) AttributeError: NO such attr bbbbbb

可见, 当我们去访问一个并未被定义的属性之时, 依旧会率先进行调用, 依据属性查找的原则, 在实例之中以及类里面都没能找到这个属性, 于是便会执行。到了此地, 我们也就知晓了其属性的查找顺序, 以及执行顺序。

当回过头去看时, 在调用类以及实例的属性之际会进行无条件调用, 所以能够将其用于权限鉴别这样的操作, 还能用于日志记录等方面;进而在属性未被找到的情形下会予以执行, 所以能够借助它来开展一些兜底的操作, 由此可见。

另外, 要留意重写期间的循环陷阱, 返回语句得写成.( ) , 别运用 self.xxx , 不然 self 等同于再次指向自身, 进而会无条件展开调用, 由此踏入无限循环。

最后的我们查看类和实例的属性,看看又什么不同

t = T() print(t.__dict__) print(T.__dict__) ------结果如下-------- 1 getattribute called, item is __dict__ {'a': 123, 'not_desc': 'instance not_desc'} {'__module__': '__main__', 'desc': <__main__.Descriptor object at 0x0000021FD20C0128>, 'Not_Desc': <__main__.NotDescriptor object at 0x0000021FD20C0160>, '__init__': , 'func': , '__getattribute__': , '__getattr__': , '__dict__': , '__weakref__': , '__doc__': None}

由此能够看出, 实例t具备的仅仅是在init里所定义的那些属性, 然而, 类T当中才存在着诸如描述器以及非描述器之类的属性。

http://www.jsqmd.com/news/1021292/

相关文章:

  • Spring Boot Excel导出实战:从POI原理到百万级数据优化
  • 奇异矩阵:数据科学中必须读懂的线性代数诊断信号
  • 2026年饲料第三方检测机构综合评述:市场格局、服务能力与案例解析 - 优质品牌商家
  • 临朐、青州短视频代运营公司怎么选,靠谱的有哪些 - 工业品网
  • 2026年铜切削油品牌选择指南:工艺适配与行业应用深度分析 - 优质品牌商家
  • 2026考场防作弊设备选购指南:中高考手机信号屏蔽仪哪家强?实战案例与厂商深度评测 - 优质品牌商家
  • 2026年自贡中专择校指南:如何从就业、升学、管理三大维度选中专?附多校实测分析 - 优质品牌商家
  • Everything:基于USN日志的Windows极速文件名搜索工具原理与实战
  • AI岗位井喷?1亿数据揭示真相:收藏这份进阶指南,小白也能抓住大模型红利!
  • Gemini 3.1原生协同:谷歌AI如何重构操作系统级交互
  • Superpowers工程化实践:AI编程的质量门禁与开发流水线
  • 中学综合教学楼设计施工全流程解析:从功能布局到系统集成
  • 宏科印业推荐哪家?综合对比与评价 - 工业品网
  • 华大九天EDA工具:国产芯片设计软件的核心价值与实战评估
  • LLM成本优化2026年中实战:把Token花费砍半的7个工程手段
  • 凯撒旅业全资控股凯撒海湾,共绘海洋文旅新蓝图 - 品牌2026
  • 5分钟掌握Photoshop图层批量导出终极指南:Export Layers To Files Fast完全教程
  • 数据分析选Python还是R?一文帮你看清python ide的门道
  • 如何选择靠谱的Acetron GPPOMC供应商?价格指南 - 工业品网
  • 2026年6月市场评价高的联轴器生产厂家推荐,齿式传动轴/传动轴/球齿联轴器/挠性联轴器,联轴器实力厂家怎么选择 - 品牌推荐师
  • 3大核心技术深度解析:EASY-HWID-SPOOFER如何实现Windows内核级硬件指纹伪装
  • Git soft reset 原理与高阶协作实践:重写提交历史的可控方法
  • NoC组件之Router微架构解析(四)仲裁
  • 555定时器无稳态模式详解:从原理到实战的矩形波生成指南
  • Kinovea运动分析软件:5分钟快速上手指南与实战技巧
  • OBS多平台直播插件:3步实现YouTube、Twitch、B站同步推流
  • 多相机兼容驱动方案:从抽象接口到工业实践
  • DPDK高性能交换机深度实战:一次FIB更新风暴引发的转发抖动故障分析
  • 对比实验全流程指南:从A/B测试设计到结果分析与决策
  • Python两位小数处理:四舍五入、银行家舍入与decimal精度实战