Python的__getattr__和__getattribute__
__getattr__
__getattr__在当前主流的Python版本中都可用,重载__getattr__方法对类及其实例未定义的属性有效。也就属性是说,如果访问的属性存在,就不会调用__getattr__方法。这个属性的存在,包括类属性和实例属性。
Python官方文档的定义
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for
self).nameis the attribute name.
class ClassA:
x = 'a'
def __init__(self):
self.y = 'b'
def __getattr__(self, item):
return '__getattr__'
if __name__ == '__main__':
a = ClassA()
# 输出结果 a
print(a.x)
# 使用实例直接访问实例存在的实例属性时,不会调用__getattr__方法
# 输出结果 b
print(a.y)
# 使用实例直接访问实例不存在的实例属性时,会调用__getattr__方法
# 输出结果 __getattr__
print(a.z)
__getattribute__
__getattribute__仅在新式类中可用,重载__getattrbute__方法对类实例的每个属性访问都有效。
Python官方文档的定义
Called unconditionally to implement attribute accesses for instances of the class.
示例代码:
class ClassA:
x = 'a'
def __init__(self):
self.y = 'b'
def __getattribute__(self, item):
return '__getattribute__'
if __name__ == '__main__':
a = ClassA()
# 使用实例直接访问存在的类属性时,会调用__getattribute__方法
# 输出结果 __getattribute__
print(a.x)
# 使用实例直接访问实例存在的实例属性时,会调用__getattribute__方法
# 输出结果 __getattribute__
print(a.y)
# 使用实例直接访问实例不存在的实例属性时,也会调用__getattribute__方法
# 输出结果 __getattribute__
print(a.z)
运行结果:
__getattribute__
__getattribute__
__getattribute__
另外,当同时定义__getattribute__和__getattr__时,__getattr__方法不会再被调用,除非显示调用__getattr__方法或引发AttributeError异常。
示例代码(__getattr__方法不会再被调用):
class ClassA:
def __getattr__(self, item):
print('__getattr__')
def __getattribute__(self, item):
print('__getatttribute__')
if __name__ == '__main__':
a = ClassA()
a.x
运行结果:
__getatttribute__
由于__getattr__只针对未定义属性的调用,所以它可以在自己的代码中自由地获取其他属性,而__getattribute__针对所有的属性运行,因此要十分注意避免在访问其他属性时,再次调用自身的递归循环。
当在__getattribute__代码块中,再次执行属性的获取操作时,会再次触发__getattribute__方法的调用,代码将会陷入无限递归,直到Python递归深度限制(重载__setter__方法也会有这个问题)。
示例代码(无限递归):
class ClassA:
x = 'a'
def __getattribute__(self, item):
print('__getattribute__')
return self.item
if __name__ == '__main__':
a = ClassA()
a.x
运行结果引发异常,提示达到最大递归深度
ecursionError: maximum recursion depth exceeded
同时,也没办法通过从__dict__取值的方式来避免无限递归
class ClassA:
x = 'a'
def __getattribute__(self, name):
return self.__dict__[name]
if __name__ == '__main__':
a = ClassA()
# 无限递归
a.x
为了避免无限递归,应该把获取属性的方法指向一个更高的超类,例如object(因为__getattribute__只在新式类中可用,而新式类所有的类都显式或隐式地继承自object,所以对于新式类来说,object是所有新式类的超类)。
修改代码(避免无限递归循环):
class ClassA:
x = 'a'
def __getattribute__(self, item):
print('__getattribute__')
return super().__getattribute__(self, item)
if __name__ == '__main__':
a = ClassA()
print(a.x)
运行结果正常:
__getattribute__
a
参考资料:
https://docs.python.org/3/reference/datamodel.html
Python的__getattr__和__getattribute__的更多相关文章
- 浅谈Python 中 __getattr__与__getattribute__的区别
__getattr__与__getattribute__均是一般实例属性截取函数(generic instance attribute interception method),其中,__getatt ...
- python魔法方法:__getattr__,__setattr__,__getattribute__
python魔法方法:__getattr__,__setattr__,__getattribute__ 难得有时间看看书....静下心来好好的看了看Python..其实他真的没有自己最开始想的那么简单 ...
- python中的__getattr__、__getattribute__、__setattr__、__delattr__、__dir__
__getattr__: 属性查找失败后,解释器会调用 __getattr__ 方法. class TmpTest: def __init__(self): self.tmp = 'tmp12 ...
- 第8.33节 Python中__getattr__以及__getattr__与__ getattribute__的关系深入剖析
一. 引言 前面几节分别介绍了Python中属性操作捕获的三剑客:__ getattribute__方法.__setattr__方法.__delattr__方法,为什么__ getattribute_ ...
- 一些代码 II (ConfigParser、创建大文件的技巧、__getattr__和__getattribute__、docstring和装饰器、抽象方法)
1. ConfigParser format.conf [DEFAULT] conn_str = %(dbn)s://%(user)s:%(pw)s@%(host)s:%(port)s/%(db)s ...
- python __setattr__, __getattr__, __delattr__, __call__
python __setattr__, __getattr__, __delattr__, __call__ getattr `getattr`函数属于内建函数,可以通过函数名称获取 value = ...
- python之 __getattr__、__getattr__、__getitem__、__setitem__ 使用
python之 __getattr__.__getattr__.__getitem__.__setitem__ 使用 __getattr__内置使用点号获取实例属性属性如 s.name,自调用__ge ...
- python魔法函数之__getattr__与__getattribute__
getattr 在访问对象的属性不存在时,调用__getattr__,如果没有定义该魔法函数会报错 class Test: def __init__(self, name, age): self.na ...
- Python魔法方法__getattr__和__getattribute__详解
在Python中有这两个魔法方法容易让人混淆:__getattr__和getattribute.通常我们会定义__getattr__而从来不会定义getattribute,下面我们来看看这两个的区别. ...
随机推荐
- react-native从开始趟的坑
好多天没更了..... 之前用的华为手机老人机真机调试的,最近几天换了小米,又遇上了坑... 跟之前所有手机一样打开开发者模式,开发者模式是(关于手机--版本号---一直点啊点--退出---辅助功能里 ...
- webpack loader加载器
配置loader,通过加载器处理文件,例如css sass less等,告诉webpack每一种文件都需要使用什么来加载器来处理. 1.node.js安装好之后也会自动默认安装好npm,所以cmd c ...
- 17. ZooKeeper常见的分布式系统任务——屏障
以后几节中主要介绍以下内容: 如何执行领导者选举,组员管理和两阶段提交协议等常见的分布式系统任务 如何实现一些分布式数据结构,如屏障(barrier),锁(lock)和队列(queue) 这一章中概述 ...
- weex加入iconfont
weex加入图标可能是项目开发中最头疼的事情了,还好有 阿里巴巴矢量图标库解决了开发时的图标问题,下面我们一起来踩坑吧<text class="left"></ ...
- iscroll使用之页面卡顿问题
最近在开发项目时,遇到一个问题,使用iscroll实现的页面滚动,测试时发现在chrome浏览器中的模拟移动设备页面不能平滑滚动,有卡顿现象,在android手机端也有同样的问题. 在github上搜 ...
- Caffe-5.2-(GPU完整流程)训练(依据googlenet微调)
上一篇使用caffenet的模型微调.但由于caffenet有220M太大,測试速度太慢.因此换为googlenet. 1. 训练 迭代了2800次时死机,大概20分钟. 使用的是2000次的模型. ...
- 2016.3.17__CSS3动画__第十一天
CSS3动画 假设您认为这篇文章还不错,能够去H5专题介绍中查看很多其它相关文章. 通过 CSS3,我们能够创建动画,这能够在很多网页中取代动绘图片.Flash 动画以及 JavaScript. 今日 ...
- 小谈iOS屏幕适配问题
首先,我么我们要观察一下5,6和6Plus的尺寸比例关系.发现了他们的关系后待会做兼容就明白了. 很明显能看出这三种屏幕的尺寸宽高比是差不多的,因此可以在5的基础上,按比例放大来兼容6和6Plus的屏 ...
- Android查缺补漏--Service和IntentService
Service的运行不依赖界面,即使程序被切换到后台,Service仍然能够保持正常运行.当某个应用程序进程被杀掉时,所有依赖于该进程的Service也会停止运行. Service 分为启动状态和绑定 ...
- 事务处理操作(COMMIT,ROLLBACK)。复制表。更新操作UPDATE实际工作中一般都会有WHERE子句,否则更新全表会影响系统性能引发死机。
更新操作时两个会话(session)同时操作同一条记录时如果没有事务处理操作(COMMIT,ROLLBACK)则会导致死锁. 复制表:此方法Oracle特有