ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python __getattribute__、__getattr__、__setattr__详解

2022-03-09 14:04:20  阅读:182  来源: 互联网

标签:__ setattr python getattribute dict 方法 属性


 

本文仅作记录,原文地址:https://www.cnblogs.com/sheshouxin/p/10448056.html

 

 

 

__getattribute__

官方文档中描述如下:

该方法可以拦截对对象属性的所有访问企图,当属性被访问时,自动调用该方法(只适用于新式类)。因此常用于实现一些访问某属性时执行一段代码的特性。

需要注意的是,正式由于它拦截对所有属性的访问(包括对__dict__的访问),在使用中要十分小心地避开无限循环的陷阱。在__getattribute__方法中访问当前实例的属性时,唯一安全的方式是使用基类(超类) 的方法__getattribute__(使用super)。例如:

通过上图中的代码示例可以看出,一旦实现了__getattribute__方法,所有通过对象访问的属性(包括类属性)都会被拦截,而直接通过类访问类属性则不会。

注意:当访问的属性不存在并重载(覆盖基类对某方法的默认实现)了__getattribute__方法时,该方法不会主动抛出AttributeError异常。上图中捕获的AttributeError异常,是由基类__getattribute__方法实现并抛出。

常见的错误用法示例:

在实现__getattribute__方法时访问对象自身的属性,程序陷入无限循环直到崩溃。

__getattr__

官方文档描述如下:

__getattr__方法的自动执行,需要满足两个条件:一是访问对象属性;二是触发AttributeError异常。代码示例如下:

上图中,调用不存在的job属性首先调用__getattribute__方法(如果该方法未定义,会调用基类的__getattribute__方法),触发AttributeError异常并自动捕获,然后才调用__getattr__方法。

错误用法示例如下:

重载了__getattribute__方法,却没有主动抛出AttributeError异常的机制,或者抛出一个其它类型的异常,__getattr__方法都不会执行。

__setattr__

试图给属性赋值时自动调用该方法,例如:

之所以会执行三次print函数,是因为在__init__方法中,对象A初始化时给属性name和age赋值时,触发了__setattr__方法。使用该方法是同样需要十分小心避免无限循环陷阱。

错误用法示例如下:

可以看出,在__setattr__方法中,不能直接给属性赋值,而通常的做法是使用__dict__魔法属性。__dict__属性是一个字典,所有的实例属性都存储在这个字典中,而修改__dict__字典中的键值对成员不会触发__setattr__方法,这里应注意与直接修改__dict__的值的区别。

注意:如果定义__setattr__方法的同时定义了__getattribute__方法,那么在修改__dict__字典中的键值对时,由于调用了self.__dict__属性,同样会触发__getattribute__方法,使用时应格外小心。代码示例如下:

上图示例代码中,每调用一次__setattr__就会调用一次__getattribute__。

注意赋值语句与属性调用的区别:self.__dict__ = {}是赋值语句,不会触发__getattribute__方法,但触发__setattr__方法;self.__dict__[name] = value语句,先调用self.__dict__属性,得到dict对象后再修改其成员,因此会触发__getattribute__方法。 

以上。

标签:__,setattr,python,getattribute,dict,方法,属性
来源: https://www.cnblogs.com/Rachel-84351228/p/15984821.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有