鱼C论坛

 找回密码
 立即注册
查看: 1017|回复: 5

[已解决]小甲鱼45讲的问题,求教!!!

[复制链接]
发表于 2020-7-14 16:39:18 | 显示全部楼层 |阅读模式
10鱼币
求教!!!
class Rectangle:
    def __init__(self, width=0, height=0):
        self.width = width
        self.height = height

    def __setattr__(self, name, value):
        if name == 'square':
            self.width = value
            self.height = value
        else:
            self.name = value

    def getArea(self):
        return self.width *self.height
这是小甲鱼45讲魔法方法时的代码,这么写会因为一直给self.name赋值触发__setattr__导致程序死循环,改成super().__setattr__(name, value)后恢复正常
我有三个个问题
1.为什么if下面的赋值操作不会触发__setattr__()导致死循环
2.为什么在重写的这句 super().__setattr__(name, value)里面没有self参数了,这个难道不是魔法方法里固定的参数么?
3.书上写的可以改成self.__dict__[name] = value,请问为什么这样写就不算是这个类本身的属性了,不触发死循环么?
最佳答案
2020-7-14 16:39:19


1.为什么if下面的赋值操作不会触发__setattr__()导致死循环


你的代码就算符合 if 条件也会进入死循环,甲鱼哥不会照成死循环的是因为 else 调用父类的__settatr__ 方法,而你这里并没有调用父类

而是重新赋值 self.name = value ,这个时候就会导致又进行了赋值操作,然后继续调用自身的 __setattr__ 方法

当你把 else 内容删去时候,你调用自己__setattr__ 方法时候,因为第二次递归 name 不会等于 square 所以不会进入 if 条件 ,也就不会照成无限递归

2.为什么在重写的这句 super().__setattr__(name, value)里面没有self参数了,这个难道不是魔法方法里固定的参数么?


super() 此时就代表着 self ,而且代表的是 父类,这和你实例化对象时候一个道理,你设置一个A类,__init__方法不是也有 self,但不需要你传入,就是因为 实例化时候会将实例对象自动传入

3.书上写的可以改成self.__dict__[name] = value,请问为什么这样写就不算是这个类本身的属性了,不触发死循环么?


你先要了解 __dict__属性,是查看对象内部所有属性名和属性值组成的字典的作用,你直接对字典这样 = 操作是添加元素,不是赋值操作,所以不会调用__settar__方法


最佳答案

查看完整内容

你的代码就算符合 if 条件也会进入死循环,甲鱼哥不会照成死循环的是因为 else 调用父类的__settatr__ 方法,而你这里并没有调用父类 而是重新赋值 self.name = value ,这个时候就会导致又进行了赋值操作,然后继续调用自身的 __setattr__ 方法 当你把 else 内容删去时候,你调用自己__setattr__ 方法时候,因为第二次递归 name 不会等于 square 所以不会进入 if 条件 ,也就不会照成无限递归 super() 此时就代表着 ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-7-14 16:39:19 | 显示全部楼层    本楼为最佳答案   


1.为什么if下面的赋值操作不会触发__setattr__()导致死循环


你的代码就算符合 if 条件也会进入死循环,甲鱼哥不会照成死循环的是因为 else 调用父类的__settatr__ 方法,而你这里并没有调用父类

而是重新赋值 self.name = value ,这个时候就会导致又进行了赋值操作,然后继续调用自身的 __setattr__ 方法

当你把 else 内容删去时候,你调用自己__setattr__ 方法时候,因为第二次递归 name 不会等于 square 所以不会进入 if 条件 ,也就不会照成无限递归

2.为什么在重写的这句 super().__setattr__(name, value)里面没有self参数了,这个难道不是魔法方法里固定的参数么?


super() 此时就代表着 self ,而且代表的是 父类,这和你实例化对象时候一个道理,你设置一个A类,__init__方法不是也有 self,但不需要你传入,就是因为 实例化时候会将实例对象自动传入

3.书上写的可以改成self.__dict__[name] = value,请问为什么这样写就不算是这个类本身的属性了,不触发死循环么?


你先要了解 __dict__属性,是查看对象内部所有属性名和属性值组成的字典的作用,你直接对字典这样 = 操作是添加元素,不是赋值操作,所以不会调用__settar__方法


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-7-14 16:58:29 | 显示全部楼层
1. 为什么if下面的赋值操作不会触发__setattr__()导致死循环

if下面的复制操作会触发一次递归,而下一次执行的便是else里面的内容了,所以只要保证else下的内容不会触发递归就可以了


2.为什么在重写的这句 super().__setattr__(name, value)里面没有self参数了,这个难道不是魔法方法里固定的参数么?

super()会返回一个类对象,执行 "对象.方法()" 这样的语句的之后,会自动传入self参数,也可以理解为super()会自动传入self参数


3.书上写的可以改成self.__dict__[name] = value,请问为什么这样写就不算是这个类本身的属性了,不触发死循环么?

这样不是一个属性赋值而是给一个字典里面添加元素,不会触发递归
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-7-14 16:59:21 | 显示全部楼层
Twilight6 发表于 2020-7-14 16:56
你的代码就算符合 if 条件也会进入死循环,甲鱼哥不会照成死循环的是因为 else 调用父类的__settatr ...

晚了一步
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-7-14 17:04:05 | 显示全部楼层
KevinHu 发表于 2020-7-14 16:58
1. 为什么if下面的赋值操作不会触发__setattr__()导致死循环

if下面的复制操作会触发一次递归,而下一次 ...

谢谢您,我应该设置几个人都能拿币的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-8-4 16:39:40 | 显示全部楼层
悟了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-13 17:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表