python中__setattr__的探索

在类的构造方法__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

你可能感兴趣的:(python,开发语言,前端)