在类的构造方法__init__对类的属性赋值时,会自动调用__setattr__方法。
问题一:
如果只设置一个属性的值时,只调用一次__setattr__方法;如果给多个属性赋值时,python是如何处理的呢?是每给一个属性赋值时,调用一次__setattr__方法呢,还是全部属性赋值时只调用一次__setattr__方法呢?
本人查了一些资料,都没有具体说明,因此,做了一个测试,结果证明,是每给一个属性赋值时,调用一次__setattr__方法,需要给几个属性赋值,就调用几次__setarrt__方法。
参见下例代码:
class Rectangle:
def __init__(self,width,height) :
print('第一次设置属性')
self.width = width
print('第二次设置属性')
self.height = height
def __setattr__(self,name,value) :
print('---设置%s属性' % name)
if name == 'size' :
self.width, self.height = value
else :
self.__dict__[name] = value
输出如下:
第一次设置属性
—设置width属性
第二次设置属性
—设置height属性
问题二:
查找相关资料发现,在使用__setattr__方法时,不能再次直接对属性赋值,否则代码会陷入死循环(原因是在__setattr__方法再次直接对属性赋值时,仍会自动调用__setattr__方法)。那么,如果需要在__setattr__方法内部对属性赋值怎么办呢?
有两个方法,一是通过字典(dict)进行操作;二是通过super()调用父类方法进行操作。
代码如下:
class Rectangle:
def __init__(self,width,height) :
print('第一次设置属性')
self.width = width
print('第二次设置属性')
self.height = height
def __setattr__(self,name,value) :
print('---设置%s属性' % name)
if name == 'size' :
self.width, self.height = value
else :
self.__dict__[name] = value #利用字段对name属性赋值
#super().__setattr__.(name) #调用父类方法
#self.name = value #会陷入死循环
读者可以通过注释下列不同代码来测试其效果。
rect = Rectangle(3,4)
#print(rect.size)
rect.size = 6,8
print(rect.width,rect.height)
#del rect.size
#print(rect.size)
当前代码输出如下:
第一次设置属性
—设置width属性
第二次设置属性
—设置height属性
—设置size属性
—设置width属性
—设置height属性
6 8