波大大12138 发表于 2020-6-23 20:30:31

关于setattr的疑惑

class Rectangle:
    def __init__(self,width=0,height=0):
#发生赋值操作则会自动触发__setattr__(r1,width,0)
      self.width=width
      self.height=height
#赋值会触发setattr;else语句中的self.name会出现自动递归的情况
    def __setattr__(self,name,value):
      if name=='square':
            self.width=value
            self.height=value
      else:
         super().__setattr__(name,value)#super()就是self参数不用写在括号里
#获得面积
    def getArea(self):
      return self.width*self.height
            

我想问一下在整个__setattr__的方法中的else语句里面,是小甲鱼课堂上已经做过修改的之后的代码改之前这一句是:self.time=value错误的原因是:发生赋值操作自动会触发__setattr__于是就陷入了无限的递归。我想问一下在该方法下面的if语句下面还有一个self.width,self.height的赋值操作为什么这两个语句就不用担心会触发该方法再无限递归下去呢?

波大大12138 发表于 2020-6-23 20:31:04

@Twilight6

小甲鱼的铁粉 发表于 2020-6-23 20:45:36

波大大12138 发表于 2020-6-23 20:31
@Twilight6

{:10_257:}

Twilight6 发表于 2020-6-23 20:57:17



首先 __init__ 方法里面有两个赋值操作:
self.width=width
self.height=height

此时假设你 实例化一个对象 r = Rectangle(5,100) 那么 __init__ 方法会自动执行:
self.width = 5
self.height = 100
这两个赋值操作会调用直接的 __setattr__ ;先来看第一个 self.width=5因为这里进行了赋值操作,所以调用了自己的 __setattr__ 方法

在 __setattr__ 方法中 name参数指的就是被赋值的变量名,简单说就是等号左边的,而这里就是指 width ,而 value 是等号右边的 就是你传入的 5

也就是你赋值self.width=5 时候name = 'width'而 value = 5

__setattr__ 方法中首先进行判断变量名 是否为 square ,这里很显然 name = 'width' 不等于 'square' 所以执行 else

else 是用 super 调用基类的 __setattr__方法 来给 width 赋值为 'square' ,而不是调用自己的 所以不会调用自己的 __setattr__方法

同理 self.height=height 也是一样的 , 所以这样 就不会导致 无限递归调用 __setattr__方法 的情况发生了,因为赋值操作到最后都是执行 父类的 __setattr__ 方法

而不是自己类的 __setattr__ 方法



波大大12138 发表于 2020-6-24 09:03:40

Twilight6 发表于 2020-6-23 20:57
首先 __init__ 方法里面有两个赋值操作:




这里我其实想问的是:在__init__方法里面如果初始化了一个变量就叫做'square',那么在下面执行setattr的时候if语句就成立了就会执行self.width和self.height的赋值操作那么这又会重新调用setattr陷入无限递归了,这是怎么回事呢,不会出错吗?

波大大12138 发表于 2020-6-24 09:13:51

@Twilight6

Twilight6 发表于 2020-6-24 09:20:50

波大大12138 发表于 2020-6-24 09:03
这里我其实想问的是:在__init__方法里面如果初始化了一个变量就叫做'square',那么在下面执行setattr的 ...

不会啊,你其实如果理解了我上面的例子,你就会理解这个

当你初始化了一个变量叫 square ,会自动调用__setattr__方法if 判断条件成立,赋值 :
self.width = value
self.height = value

然后其实赋值 就是赋值了 self.width,self.height 重新调用__setattr__方法,这次 因为name 都不为 square 所以执行else ,就成功赋值了呀?

不会无限递归,你先理解好我 4 L 的,自然会理解这个
页: [1]
查看完整版本: 关于setattr的疑惑