setattr(self, item, value):
当试图对对象的item特性赋值的时候将会被调用。
我们在编程当中如果对__setattr__这一方法进行操作修改的时候,有时候会造成无限递归。
class Mutilate:
def __init__(self,a=0,b=0):
self.a = a
self.b = b
def __setattr__(self,name,value):
if name == 'square':
self.a = value
self.b = value
else:
self.name = value
#super().__setattr__(name,value)
def getresult(self):
return self.a * self.b
这里以一个乘法为例子,当我们输入:r1=Mutilate(10,20)企图计算10*20的时候,在命令行会返回我们无限递归的错误。
我们来看一下上述的源代码:
在我们对a,b赋值的时候,程序转到的是def__setattr__中的if-else语句中的else语句,即self.name = value。这里的赋值“=”又会让程序重新跳到__setattr__这里,那么就会继续执行def__setattr__中的if语句内的else语句,即self.name = value。所以这样写程序便会跳到无限递归里面,在命令行操作就会出现红色提醒的错误。
我们可以对程序的else语句内赋值语句重新修改,这里介绍super()函数,这个函数可以保存继承的父类的属性。具体操作如下:
class Mutilate:
def __init__(self,a=0,b=0):
self.a = a
self.b = b
def __setattr__(self,name,value):
if name == 'square':
self.a = value
self.b = value
else:
super().__setattr__(name,value)
def getresult(self):
return self.a * self.b
运行结果如下图所示:
我们在给予a,b初始值2和9之后,由于name !=‘square’,因此直接进入else循环语句,这样第一个name=a,此时value=2,把2赋值给a,第二次进入后name = b,此时value =9,将9赋值给b。最后执行getresult语句,得到二者的乘积。
如果我们声明了类型是’square’后,会出现下列的结果:
这里程序先进入if的判断,然后进入self.a = value。此时注意!!!程序在执行赋值的时候重新进入了 __setattr__语句当中,但这个时刻,name已经是a了,所以第二次又进入了else语句当中,将value(值为9)赋给name(此时是a),完成了第一次赋值。b的赋值过程类似于a,这里就不细说了。
总结:Python中的__setattr__同一般类型的函数不同,这个函数属于基础的函数,因此在对它进行加工的时候要千万小心赋值语句的使用。应当注意:改变不能乱编!!!