一、 引言

《第8.26节 重写Python类中的__getattribute__方法实现实例属性访问捕获》章节介绍了__getattribute__方法,可以通过重写该方法,截获所有通过“实例名.属性名”访问实例变量、类变量、实例方法的所有操作,这是一个非常符合Python风格的方法。类似的,Python提供了__setattr__方法截获所有给属性赋值的能操作,在本节的前2节介绍了调用__setattr__方法进行属性设置的方法,本节将介绍重写__setattr__方法并以此验证所有属性值的修改Python都会隐式地调用__setattr__方法。

二、 重写__setattr__方法

虽然可以动态重写__setattr__方法,但老猿并不建议这样做,我们还是建议在类中直接通过定义重写__setattr__()方法你,这样最高效也最符合编程者的思维。

  1. 语法:setattr(self, name, value)
  2. 语法释义:

    1)self,就是对象自身,如果有不理解的,请参考老猿前面的博文《第7.5节 揭开Python类中self的面纱》

    2)name:需要定义的属性名字,为字符串类型。注意属性不仅是实例变量,也可能是实例方法,但不会是类变量,因为触发该方法只能通过“对象.属性”触发,而在使用该方式给类变量赋值时,并不是赋值给类变量,而是定义了一个与类变量同名的实例变量。具体请参考老猿前面的博文《第7.12节 可共享的Python类变量》

    3)value:属性需要设置的值;
  3. 重写一个类的实例方法__setattr__后,在该类的任何个属性被尝试赋值时将调用重写的方法,这个调用会取代正常机制(即将值保存到实例字典)。因此在自定义类中重写__setattr__方法后,如果需要继续执行赋值给一个实例属性的任务,它应该调用同名的父类方法,例如 object.__setattr__方法, 或执行“实例.dict[属性名]=值”,如果调用自身的__setattr__方法执行赋值语句,会导致__setattr__方法的嵌套递归调用。

三、 案例

  1. 案例说明

    1)定义类Car,类中除了构造方法,还有实例方法drive1和重写的__setattr__;

    2)重写的__setattr__方法就是在调用时输出相关属性及其要设置的值,并为了保障属性值正常设置,调用了父类的__setattr__方法去设置属性的值;

    3)在类体外定义了实例car;

    4)在类体外定义一个函数fdrive,在定义实例后,将该函数动态赋值给类的实例变量drive2,并通过MethodType实现实例与该函数的绑定;

    5)执行相关方法查看重写的__setattr__方法的执行情况以及对__dict__的影响。

  2. 案例代码

>>> from types import MethodType #导入MethodType方法
>>> def fdrive(self,distance):
print(f"In function fdrive:distance={distance}")
self.totaldistance += distance #定义一个函数,准备用于赋值给类的实例方法属性 >>> class Car():
def __init__(self, power):
self.power = power
self.totaldistance=0 def drive1(self,distance):
print(f"In method drive:distance={distance}")
self.totaldistance+=distance def __setattr__(self,name,value):
print(f"execute __setattr__:name={name},value={value}")
self.__dict__[name]= value >>> car = Car('汽油发动机')
execute __setattr__:name=power,value=汽油发动机
execute __setattr__:name=totaldistance,value=0
>>> car.drive1(100)
In method drive:distance=100
execute __setattr__:name=totaldistance,value=100
>>> car.__setattr__('drive2',MethodType(fdrive,car)) #用函数定义实例方法drive2
execute __setattr__:name=drive2,value=<bound method fdrive of <__main__.Car object at 0x00000000045E5A90>>
>>> car.drive2(100)
In function fdrive:distance=100
execute __setattr__:name=totaldistance,value=200
>>> car.__dict__ #查看自定义实例变量
{'power': '汽油发动机', 'totaldistance': 200, 'drive2': <bound method fdrive of <__main__.Car object at 0x00000000045E5A90>>}
>>>
  1. 执行截图



5. 案例总结

1)通过上述执行情况可以确认,无论是类体内的实例方法(含构造方法)执行还是类体外的实例变量赋值,都会触发__setattr__方法的执行。因此该自定义方法可以完全捕获所有对属性的设置,如果需要加控制逻辑可以在该自定义方法中增加;

2)动态绑定的实例方法,与类体内定义的实体方法不同,动态定义的在__dict__中有一个实例变量,而类体内预定义的则没有。这是因为动态定义本身就是一个赋值语句,肯定会触发实例变量的增加。

本节结合案例介绍了重写__setattr__方法的实现以及相关注意事项,通过重写类的实该方法__setattr__,可以捕获对该类的所有属性定义和赋值。

老猿Python,跟老猿学Python!

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


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

第8.30节 重写Python __setattr__方法实现属性修改捕获的更多相关文章

  1. 第8.26节 重写Python类中的__getattribute__方法实现实例属性访问捕获

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

  2. Python魔法方法之属性访问 ( __getattr__, __getattribute__, __setattr__, __delattr__ )

    通常情况下,我们在访问类或者实例对象的时候,会牵扯到一些属性访问的魔法方法,主要包括: ① __getattr__(self, name): 访问不存在的属性时调用 ② __getattribute_ ...

  3. python魔法方法大全

    1.python魔法方法详解: python魔法方法是可以修改重载的,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而 ...

  4. 第8.22节 Python案例详解:重写 “富比较”方法控制比较逻辑

    一. 案例说明 本节定义一个小汽车的类Car,类中包括车名carname.百公里油耗oilcostper100km.价格price三个属性.然后实现__lt__.__gt__.__le__.__ge_ ...

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

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

  6. 第8.17节 Python __repr__方法和__str__方法、内置函数repr和str的异同点对比剖析

    一. 引言 记得刚开始学习Python学习字符串相关内容的时候,查了很多资料,也做了些测试,对repr和str这两个函数的返回值老猿一直没有真正理解,因为测试发现这两个函数基本上输出时一样的.到现在老 ...

  7. 第8.29节 使用MethodType将Python __setattr__定义的实例方法与实例绑定

    一. 引言 在<第7.14节Python类中的实例方法解析>介绍了使用"实例对象名.方法名 = MethodType(函数, 对象)"将动态定义的方法与实例进行绑定 在 ...

  8. python 魔法方法补充(__setattr__,__getattr__,__getattribute__)

    python 魔法方法补充 1 getattribute (print(ob.name) -- obj.func())当访问对象的属性或者是方法的时候触发 class F(object): def _ ...

  9. Python中自定义类如果重写了__repr__方法为什么会影响到str的输出?

    这是因为Python3中,str的输出是调用类的实例方法__str__来输出,如果__str__方法没有重写,则自动继承object类的__str__方法,而object类的__str__方法是调用_ ...

随机推荐

  1. W3C中不同标准的含义

    学习CSS/HTML的过程中,当出现释义冲突时,W3C(万维网联盟)官网所陈列的技术标准是最核心的判断参考.但是新手在查阅W3C标准索引页面时,会发现同一个属性或者模型会出现多个不同的阶段规范展示结果 ...

  2. Check Host:实时监控网站或者服务器是否可以访问

    如果你拥有一个网站,那么最重要的事情就是要保证它24小时都能够访问.不过国内的虚拟主机服务非常糟糕,经常会出现各种状况,所以我们需要一个软件,可以让我们第一时间知道网站出现了无法访问的情况,从而通知售 ...

  3. 回溯算法 - n 皇后问题

    (1)问题描述 在 n × n 格的棋盘上放置彼此不受攻击的 n 个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n 后问题等价于在 n × n 的棋盘上放置 n 个 ...

  4. IGH_Master主站配置驱动伺服电机和变频器总结

    IGH_Master主站配置驱动伺服电机和变频器总结 Ethercat是倍福公司提出的一种工业现场总线协议,具有很好的实时性,IGH是一种开源的Ethercat主站实现协议,本文总结了一下使用IGH_ ...

  5. Environment Cubemap

    要创建一个Cubemap(将您的环境捕获到一个Cubemap中),您需要去Unity Documentation复制RenderCubemapWizard.cs脚本! 然后在"Project ...

  6. 在Linux中输入命令时打错并按了enter

    今天在Linux中输入命令时,打错一个单词了,之后出现一串串的~,按ESC也没用, 并在底部出现:quit<enter> to exit vim 解决办法: 按几下 esc 确保 vim ...

  7. burp插件之跨站payload批量注入-xssValidator

    环境搭建 Phantomjs下载 csdn-burp使用xssValidator插件 cnblog-burp插件之xssValidator xssValidator使用 参考链接 cnblog-bur ...

  8. Java8用了这么久了,Stream 流用法及语法你都知道吗?

    1.简介 Stream流 最全的用法Stream 能用来干什么?用来处理集合,通过 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询,Stream API 提供了一 ...

  9. guitar pro 系列教程(十一):Guitar Pro菜单工具之MIDI效果的提升

    对于新手的一些朋友,看谱,编曲时使用Guitar Pro时,因为对其功能不是很了解而显得困难重重,导致出现的音频效果不是很理想,因此,小编今天要做的便是,单独把Guitar Pro里的MIDI效果如果 ...

  10. 一 HTML基础入门

    HTML概念 HTML是标记语言,由W3C组织提供的一套标记标签组成.其使用标记标签来描述网页,一个网页除了由大量的标签组成,还有后续要学习的css样式和JavaScript脚本组合而成. 网页与网站 ...