一、 引言

前面几节分别介绍了Python中属性操作捕获的三剑客:__ getattribute__方法、__setattr__方法、__delattr__方法,为什么__ getattribute__方法与后两者的命名规则会不同呢?为什么属性读取的方法不是__ getattr__方法呢?这是因为Python中__ getattr__方法别有用途。

二、 __getattr__与__getattribute__关系

__getattr__是Python中的内置函数,该函数可以在实例的属性查看时出现异常时执行,object类的__getattr__直接抛出异常。

__getattr__与__getattribute__都是内置方法,都是与属性查看相关的方法,当Python每次调用一个实例的属性查看时,Python会无条件进入__getattribute__中,而当对应属性不存在时,Python就会调用__getattr__来进行处理。

  1. 当默认属性访问因引发 AttributeError 而失败时__getattr__被调用,这种调用:

    1)可能是调用 __getattribute__() 时由于 name 不是一个实例属性或 self 的类关系树中的属性而引发了 AttributeError

    2)可能是对 name 特性属性调用 __get__() 时引发了 AttributeError
  2. 此方法应当返回(找到的)属性值或是引发一个 AttributeError 异常。如果属性是通过正常机制找到的,__getattr__() 就不会被调用;
  3. 重写__getattr__()时,如果重写的自定义方法不能在自定义代码中返回对应值或抛出异常,则可以调用父类的__getattr__()方法。

三、 为什么有__getattribute__还需要__getattr__

通过前面的介绍,我们知道__getattr__执行时,__getattribute__肯定会执行,__getattribute__执行时,不一定会执行__getattr__。那为什么还需要__getattr__呢?

这是Python在 __getattr__() 和 __setattr__() 之间故意设置的不对称性:

  1. 这是为了提高处理效率,__getattribute__不论什么情况查看属性都会执行,而 __getattr__只在属性错误的情况下执行,如果业务逻辑只要求错误情况下才进行捕获处理,则__getattribute__重写会导致访问效率降低;
  2. 如果出错情况下调用__getattribute__,而在处理逻辑中为了支持这种异常情况的处理可能会需要访问实例的其他属性,这会导致再次触发__getattribute__,从而可能导致嵌套调用甚至无穷尽的调用,而使用__getattr__则可以避免这种情况

四、 案例

  1. 案例说明

    案例中定义了类Car,类中有构造方法、__getattribute__和__getattr__方法,用该类定义实例对象car,通过实例访问正常的实例变量和不存在的方法、不存在的实例变量,看__getattribute__和__getattr__方法的执行情况。
  2. 源代码
>>> car = Car('汽油发动机')
>>> car.power #存在的属性查看只调用了__getattribute__
execute __getattribute__power
>>> car.drive() #一个不存在的方法drive调用了__getattribute__,同时还调用了__getattr__,最后抛出AttributeError异常
execute __getattribute__drive
execute __getattr__:name=drive
Traceback (most recent call last):
File "<pyshell#50>", line 1, in <module>
car.drive() #一个不存在的方法drive调用了__getattribute__,同时还调用了__getattr__,最后抛出AttributeError异常
File "<pyshell#47>", line 12, in __getattr__
super().__getattr__(name)
AttributeError: 'super' object has no attribute '__getattr__'
>>> car.Power #一个不存在的实例变量Power调用了__getattribute__,同时还调用了__getattr__,最后抛出AttributeError异常
execute __getattribute__Power
execute __getattr__:name=Power
Traceback (most recent call last):
File "<pyshell#51>", line 1, in <module>
car.Power #一个不存在的实例变量Power调用了__getattribute__,同时还调用了__getattr__,最后抛出AttributeError异常
File "<pyshell#47>", line 12, in __getattr__
super().__getattr__(name)
AttributeError: 'super' object has no attribute '__getattr__'
>>>
  1. 执行截图

本节介绍了__getattr__方法触发的场景,并与__getattribute__方法进行了比对,开发者可以在特定情况下重写该方法对抛出异常进行截获,如特定条件下网络访问URL的重定向。

老猿Python,跟老猿学Python!

博客地址:https://blog.csdn.net/LaoYuanPython


请大家多多支持,点赞、评论和加关注!谢谢!

第8.33节 Python中__getattr__以及__getattr__与__ getattribute__的关系深入剖析的更多相关文章

  1. 第7.19节 Python中的抽象类详解:abstractmethod、abc与真实子类

    第7.19节 Python中的抽象类详解:abstractmethod.abc与真实子类 一.    引言 前面相关的章节已经介绍过,Python中定义某种类型是以实现了该类型对应的协议为标准的,而不 ...

  2. 第7.15节 Python中classmethod定义的类方法详解

    第7.15节  Python中classmethod定义的类方法详解 类中的方法,除了实例方法外,还有两种方法,分别是类方法和静态方法.本节介绍类方法的定义和使用. 一.    类方法的定义 在类中定 ...

  3. 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解

    第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一.    引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...

  4. 第7.22节 Python中使用super调用父类的方法

    第7.22节 Python中使用super调用父类的方法 前面章节很多地方都引入了super方法,这个方法就是访问超类这个类对象的.由于super方法的特殊性,本节单独谈一谈super方法. 一.su ...

  5. 第8.23节 Python中使用sort/sorted排序与“富比较”方法的关系分析

    一. 引言 <第8.21节 Python中__lt__.gt__等 "富比较"("rich comparison")方法用途探究>和<第8.2 ...

  6. 第8.27节 Python中__getattribute__与property的fget、@property装饰器getter关系深入解析

    一. 引言 在<第7.23节 Python使用property函数定义属性简化属性访问的代码实现>和<第7.26节 Python中的@property装饰器定义属性访问方法gette ...

  7. 第11.20节 Python 中正则表达式的扩展功能:后视断言、后视取反

    一. 引言 在<第11.19节 Python 中正则表达式的扩展功能:前视断言和前视取反>中老猿介绍了前视断言和前视取反,与二者对应的还有后视断言和后视取反. 二. (?<=-)后视 ...

  8. 第14.12节 Python中使用BeautifulSoup解析http报文:使用select方法快速定位内容

    一. 引言 在<第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问>和<第14.11节 Python中使用BeautifulSo ...

  9. 第14.11节 Python中使用BeautifulSoup解析http报文:使用查找方法快速定位内容

    一. 引言 在<第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问>介绍了BeautifulSoup对象的主要属性,通过这些属性可以访 ...

随机推荐

  1. ubuntu 17.10 安装QQ

    折腾一大堆 看报错信息 正在选中未选择的软件包 wine-qqintl:i386.(正在读取数据库 ... 系统当前共安装有 185429 个文件和目录.)正准备解包 wine-qqintl_0.1. ...

  2. Inception系列之Batch-Normalization

    训练深度神经网络非常复杂,因为在训练过程中,随着先前各层的参数发生变化,各层输入的分布也会发生变化,图层输入分布的变化带来了一个问题,因为图层需要不断适应新的分布,因此训练变得复杂,随着网络变得更深, ...

  3. java类学习

    public class test4 { public static void main(String args[]) { /** * 方法定义规则 * 修饰 类型 方法名(参数){ * 要完成的动作 ...

  4. Spider_基础总结5--动态网页抓取--元素审查--json--字典

    # 静态网页在浏览器中展示的内容都在HTML的源码中,但主流网页使用 Javascript时,很多内容不出现在HTML的源代码中,此时仍然使用 # requests+beautifulsoup是不能够 ...

  5. Mongodb和Hbase的对比

    Mongodb和Hbase的对比 1.Mongodb bson文档型数据库,整个数据都存在磁盘中,hbase是列式数据库,集群部署时每个familycolumn保存在单独的hdfs文件中. 2.Mon ...

  6. hive 下载和导入数据 hive -e

    1. 从97导出dim_channel_terminal_flag表数据到txt(数据下载) hive -e 'select * from dim.dim_city' >> dim_cit ...

  7. post和get、PostMapping、GetMapping和RequestMapping

    PostMapping.GetMapping和RequestMapping PostMapping和GetMapping封装了method="",限制了method,更加规范化. ...

  8. 378. Kth Smallest Element in a Sorted Matrix(大顶堆、小顶堆)

    Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...

  9. TCC事务原理

    本文主要介绍TCC的原理,以及从代码的角度上分析如何实现的:不涉及具体使用示例.本文分析的是github中开源项目tcc-transaction的代码,地址为:https://github.com/c ...

  10. 目录方式扩展swap分区大小

    1.查看swap大小:free  -m  (-k|m|g) --以k|m|g为单位用去尾法显示大小  [root@lbg tmp]# free -m total        used        ...