属性访问课后作业
关于课后作业第三题,编写一个counter类 用于检测实时对象有多少个属性,我写了下面这个代码,感觉怪怪的,也确实没运行出来,问题出在哪里啊?class C:
def __init__(self):
self.counter=0
def __setattr__(self,name,value):
super().__setattr__(name,value)
self.counter+=1
super().__setattr__(name,value)
def __delattr__(self,name):
super().__delattr__(name)
self.counter-=1
super().__delattr__(name)
还有就是,
def __setattr__(self,name,value):
super().__setattr__(name,value)
self.counter+=1
super().__setattr__(name,value)
这种在__setattr__里面遇到赋值的时候是继续运行完后面的super().__setattr__还是会立即跳出来重新运行 def __setattr__(self,name,value) self.counter+=1 这里不应该是实例属性,而应该改成类属性。
否则你只是给实例的counter属性加了1,而不是类加1. heidern0612 发表于 2020-6-16 18:32
self.counter+=1 这里不应该是实例属性,而应该改成类属性。
否则你只是给实例的counter属性加了1,而 ...
不太明白...{:10_266:} 今天的我更强了 发表于 2020-6-16 18:59
不太明白...
self这里指的是你类的实例对象。
也就是说,你实例化的时候,传的值也包括实例本身,也就是self。
所以你不能self里的count +1,而是应该在类里面加1.
也就是说你需要在init里面加个count +=1 ,而不是实例出来的对象+=1.
那样的话,这个self.count就是跟实例绑定了,它就只是实例的属性,而不是类的属性加1了。
其他部分不用看,主要错误是再 __setattr__ 这
def __setattr__(self,name,value):
super().__setattr__(name,value)
self.counter+=1
这个函数我们只看这个部分都看出来已经是个死循环了,因为你实例化时候先__init__ 自动调用 self.counter=0
而 self.counter=0 会触发__setattr__方法,__setattr__方法进入后调用父类 进行对 self.counter=0 的赋值
然后 self.counter+=1 这个可以看成 self.counter = self.counter + 1 ,这里又再次赋值,又会调用自己 __setattr__ 然后进行 调用父类方法进行再次调用父类进行赋值self.counter = self.counter + 1 以此进入死循环 heidern0612 发表于 2020-6-16 20:41
self这里指的是你类的实例对象。
也就是说,你实例化的时候,传的值也包括实例本身,也就是self。
好像有些明白了 那第二个问题呢?求指教 谢谢
RecursionError: maximum recursion depth exceeded while calling a Python object
这个是函数的报错内容,意思就是超出系统最大的递归次数了,实际上就是无限递归了
所以你的这个代码并不能解决问题,我记得小甲鱼下节课或者下下节课就会有再课后习题那解决这个的办法
本帖最后由 Twilight6 于 2020-6-16 21:04 编辑
heidern0612 发表于 2020-6-16 20:41
self这里指的是你类的实例对象。
也就是说,你实例化的时候,传的值也包括实例本身,也就是self。
应该主要不是您说的这个错误吧,小甲鱼这颗是为了让我们知道重写 setattr 时候需要注意初始化的赋值会调用自身
而自身属性还未赋值成功就提前 + 1 导致的报错问题 Twilight6 发表于 2020-6-16 20:59
这个是函数的报错内容,意思就是超出系统最大的递归次数了,实际上就是无限递归了
所以你的这个代 ...
请问第二个问题呢? 会继续运行完还是会立即跳出来重新运行? 今天的我更强了 发表于 2020-6-16 21:01
请问第二个问题呢? 会继续运行完还是会立即跳出来重新运行?
第二个问题已经在 5 L 说了 ,你赋值第一次就开始进入无限递归了 而且没有出口不可能会执行到第二个的 super().__setattr__(name,value) Twilight6 发表于 2020-6-16 21:01
应该主要不是您说的这个错误吧,小甲鱼这颗是为了让我们知道重写 setattr 时候需要注意初始化的赋值会 ...
嗯嗯,我没看课后题。 今天的我更强了 发表于 2020-6-16 21:01
请问第二个问题呢? 会继续运行完还是会立即跳出来重新运行?
这里只留 __setattr__ 方法以便观察:
def __setattr__(self,name,value):
super().__setattr__(name,value)
self.counter+=1
super().__setattr__(name,value)
第一次 __init__ 实例化时候 self.counter=0 赋值自动调用 __setattr__ 方法然后运行第一个 super().__setattr__(name,value) ,成功将 self.counter 赋值为 0然后执行 self.counter+=1
而 self.counter+=1 可以看成 self.counter = self.counter + 1则赋值又开始自动调用 __setattr__ 方法 这个时候开始第一次递归
进入 __setattr__ 方法 运行到方法第一行 super().__setattr__(name,value) 成功赋值 self.counter = self.counter + 1 然后又执行下面的self.counter+=1
而 self.counter+=1 可以看成 self.counter = self.counter + 1则赋值又开始自动调用 __setattr__ 方法 这个时候开始第二次递归
......
...
...
..
.
.
最后报错:
RecursionError: maximum recursion depth exceeded while calling a Python object
递归超出最大限度!
这样可以理解了吧?
Twilight6 发表于 2020-6-16 21:16
这里只留 __setattr__ 方法以便观察:
对,这个就懂了,但之前问的那个我就迷糊了
class C:
def __setattr__(self,name,value):
value+=1
super().__setattr__(name,value)
这个代码,设置参数之后执行,首先遇到vlaue=value+1,然后又遇到赋值,又开始调用 def __setattr__(self,name,value) 这样不也就会无线循环下去,为什么会运行成功?
不好意思 纯小白问题比较多 今天的我更强了 发表于 2020-6-16 21:48
对,这个就懂了,但之前问的那个我就迷糊了
class C:
def __setattr__(self,name,value):
这个不一样,这个 value 是属于外部传入的数,而不属于这个类的,只有这个类里面的才会调用自己类的方法
举个例子:
c = C()
c.test = 10 # 这里的值是外部传入的 也就是 name = test 而value = 10
print(c.test)
>>> 11
在 c.test = 10 赋值过程实际上是这样的:
def __setattr__(c,name=test,value=10):
value+=1 # 10+1 = 11
super().__setattr__(name,value) # 然后调用父类方法赋值 则 test属性的值为 11 Twilight6 发表于 2020-6-16 22:27
这个不一样,这个 value 是属于外部传入的数,而不属于这个类的,只有这个类里面的才会调用自己类的方法
...
也就是这个value+=1调用的是objec里的 __setattr__,而不是我自己定义的def__setattr__这样理解对吗? 今天的我更强了 发表于 2020-6-16 22:40
也就是这个value+=1调用的是objec里的 __setattr__,而不是我自己定义的def__setattr__这样理解对吗?
嗯~差不多这个意思嘿嘿~ Twilight6 发表于 2020-6-16 22:44
嗯~差不多这个意思嘿嘿~
谢谢大佬 感激不尽
页:
[1]