__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). name is 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__的更多相关文章

  1. 浅谈Python 中 __getattr__与__getattribute__的区别

    __getattr__与__getattribute__均是一般实例属性截取函数(generic instance attribute interception method),其中,__getatt ...

  2. python魔法方法:__getattr__,__setattr__,__getattribute__

    python魔法方法:__getattr__,__setattr__,__getattribute__ 难得有时间看看书....静下心来好好的看了看Python..其实他真的没有自己最开始想的那么简单 ...

  3. python中的__getattr__、__getattribute__、__setattr__、__delattr__、__dir__

    __getattr__:     属性查找失败后,解释器会调用 __getattr__ 方法. class TmpTest: def __init__(self): self.tmp = 'tmp12 ...

  4. 第8.33节 Python中__getattr__以及__getattr__与__ getattribute__的关系深入剖析

    一. 引言 前面几节分别介绍了Python中属性操作捕获的三剑客:__ getattribute__方法.__setattr__方法.__delattr__方法,为什么__ getattribute_ ...

  5. 一些代码 II (ConfigParser、创建大文件的技巧、__getattr__和__getattribute__、docstring和装饰器、抽象方法)

    1. ConfigParser format.conf [DEFAULT] conn_str = %(dbn)s://%(user)s:%(pw)s@%(host)s:%(port)s/%(db)s ...

  6. python __setattr__, __getattr__, __delattr__, __call__

    python __setattr__, __getattr__, __delattr__, __call__ getattr `getattr`函数属于内建函数,可以通过函数名称获取 value = ...

  7. python之 __getattr__、__getattr__、__getitem__、__setitem__ 使用

    python之 __getattr__.__getattr__.__getitem__.__setitem__ 使用 __getattr__内置使用点号获取实例属性属性如 s.name,自调用__ge ...

  8. python魔法函数之__getattr__与__getattribute__

    getattr 在访问对象的属性不存在时,调用__getattr__,如果没有定义该魔法函数会报错 class Test: def __init__(self, name, age): self.na ...

  9. Python魔法方法__getattr__和__getattribute__详解

    在Python中有这两个魔法方法容易让人混淆:__getattr__和getattribute.通常我们会定义__getattr__而从来不会定义getattribute,下面我们来看看这两个的区别. ...

随机推荐

  1. 【NOIP2014提高组】寻找道路

    https://www.luogu.org/problem/show?pid=2296 满足条件的路径:路径上的所有点的出边所指向的点都与终点连通.反过来,不满足条件的路径:路径上至少一点的出边所指向 ...

  2. windows MySQL 5.6.38 安装步骤

    文章转载于此出 mysql5.6.38 1067错误 可能是自己添加 了my.ini文件 其实不需要添加这个文件,直接在mydefault.ini中修改就行了 mysql 5.6 zip解压安装配置( ...

  3. day6、Linux下如何找出7天以前的文件删除

    有些时候,由于系统产生的日志文件,使服务器的磁盘空间紧张,所以怎么删除7天以前的日志文件及让系统只保留7天以内的日志文件 方法一 使用命令:find + |xargs + ls 命令方法:find / ...

  4. Java笔记 (持续更新ing)

    目录:  1 .  GC是什么,为什么要有GC? 1. GC是什么,为什么要有GC? GC是垃圾回收的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃 ...

  5. shell脚本删除N天前的目录-----附linux和mac上date命令的不同

    背景: 每日构建的东西.按日期放到不同的目录里. 现在天的构建放到2015-06-01里,明天的就放到2015-06-02里,依次类推.时间久了.须要一个脚本删除N天前的目录.(本例中N=7.即删除一 ...

  6. SSH中的免password登录

    1:运行命令  ssh-keygen -t rsa 产生秘钥 ,位于~/.ssh目录下(假设在这期间有什么提示.一路敲击enter下去,什么都不用输入) 2:运行命令 cp  ~/.ssh/id_rs ...

  7. 二、springcloud Netflix 注册中心

    Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现.也是springcloud体系中最重要最核心的组 ...

  8. mysql主从备份+keepalived自动切换

    数据库这一层需要做到避免单点故障可以是主从备份和主主备份,主主备份可能有性能损耗和数据同步的问题.这里记录下主从备份, mysql进行备份之前确保mysql的版本是一样的,我这里用的都是mysql5. ...

  9. for in,Object.keys()与for of的区别

    for in 1.for in一般用于遍历对象的属性: 2.作用于数组的for in除了会遍历数组元素外,还会遍历自定义可枚举的属性,以及原型链上可枚举的属性:3.作用于数组的for in的遍历结果是 ...

  10. 【CSS3】颜色表示方式

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...