一、 引言

前面几节分别介绍了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. Spring Cloud 纯干货,从入门到实战

    导读 之前写过一篇SpringCloud从入门到精通的点我直达,微服务基础知识点我直达,今天我们使用Spring Cloud模拟一个电商项目.分别有以下2个服务,商品.订单.下面我们开始叭 技术栈 S ...

  2. Android网络性能监控方案

    阿里云 云原生应用研发平台EMAS 刘宝文(木睿) 背景 移动互联网时代,移动端极大部分业务都需要通过App和Server之间的数据交互来实现,所以大部分App提供的业务功能都需要使用网络请求.如果因 ...

  3. 用微信小程序做一个小电商 sku

    效果展示图 功能点概述 图一功能点有 搜索 轮播图 商品展示 图二功能点 导航栏 加入购物车 图四功能点 评论点 图五购物车 复选框 ( 全选全不选 ) 即点即改 总计结算 功能详解 1.A(搜索) ...

  4. SpringBoot第九集:整合JSP和模板引擎Freemarker/Thymeleaf(2020最新最易懂)

    SpringBoot第九集:整合JSP和模板引擎(2020最新最易懂) 当客户通过前端页面提交请求后,我们以前是怎么做的?后端接收请求数据,处理请求,把响应结果交给模板引擎JSP,最后将渲染后的JSP ...

  5. 18FlaskRESTful

    一,虚拟环境下安装(win) 在安装这个环节发现了很多问题,pycharm里装了之后发现根本引用不了,查明原因是因为第三方库pycharm无法识别. 解决办法:进入虚拟环境直接pip. 二,基本使用 ...

  6. c语言 字符指针数组的用法

    #include <stdio.h> #include <stdlib.h> int main(){ //字符数组的使用 char str[] = {'z','b','c',' ...

  7. centos 新装的常见问题

    1.没有1080分辨率 vi /etc/X11/xorg.conf Section "Monitor" Identifier "Monitor0" Vendor ...

  8. netcore一键部署到linux服务器以服务方式后台运行

    @font-face { font-family: octicons-link; src: url("data:font/woff;charset=utf-8;base64,d09GRgAB ...

  9. 蓝鲸平台开启consul.conf UI界面

    #第一步: vi /data/bkce/etc/supervisor-consul.conf 修改参数: command=/usr/bin/consul agent -config-file=/dat ...

  10. python-网络安全编程第六天(threading多线程模块&Queue模块&subprocess模块)

    前言 昨天晚上9点多就睡了 2点起来没睡意... 那就学习吧emmmm ,拿起闲置几天的python课程学习.学习到现在5.58了 总结下 继续开始学习新的内容 多多线程? 线程(英语:thread) ...