鱼C论坛

 找回密码
 立即注册
查看: 2115|回复: 8

[技术交流] 045讲最后一题小甲鱼做错了

[复制链接]
发表于 2020-3-9 20:33:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 十月故里 于 2020-3-9 20:44 编辑

今天做到45讲习题的时候,提交之后可以看答案嘛,然后我提交的正是最后一题的答案,里面我举了两个例子,一个错误一个正确的,然后神奇的发现,小甲鱼最后一道题的答案和我错误的例子有点像
首先看看题目
2. 修改上边【测试题】第 4 题,使之可以正常运行:编写一个 Counter 类,用于实时检测对象有多少个属性。
  1. class Counter:
  2.         def __init__(self):
  3.                 self.counter=-1
  4.         def __setattr__(self,name,value):
  5.                 super().__setattr__(name,value)
  6.                 super().__setattr__('counter',self.counter+1)
  7.         def __delattr__(self,name):
  8.                 self.counter-=2
  9.                 super().__delattr__(name)
复制代码

这是我刚看到题写的第一个写法,然后检查的时候发现,只要调用到setattr的时候,counter都会+1,所以当我们对一个已存在的属性重新赋值的时候,又会导致counter+1了
  1. >>> c=Counter()
  2. >>> c.x=1
  3. >>> c.x=2
  4. >>> c.counter
  5. 2
复制代码

所以我加了个if来判断
  1. class Counter:
  2.         k=[]
  3.         def __init__(self):
  4.                 self.counter=0
  5.         def __setattr__(self,name,value):
  6.                 if name != 'counter':
  7.                         if name not in self.k:
  8.                                 self.counter+=1
  9.                                 self.k.append(name)
  10.                 super().__setattr__(name,value)
  11.         def __delattr__(self,name):
  12.                 self.counter-=1
  13.                 self.k.remove(name)
  14.                 super().__delattr__(name)
复制代码

此时就可以正常统计这个实例对象究竟创建了多少个属性啦
  1. >>> c=Counter()
  2. >>> c.x=1
  3. >>> c.x=2
  4. >>> c.counter
  5. 1
  6. >>> c.y=2
  7. >>> c.counter
  8. 2
  9. >>> del c.x
  10. >>> c.counter
  11. 1
复制代码

评分

参与人数 3荣誉 +8 鱼币 +9 贡献 +6 收起 理由
nizitao + 4 + 4 + 3 牛逼
小甲鱼 + 2 + 3 + 3 鱼C有你更精彩^_^
zltzlt + 2 + 2 无条件支持楼主!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-3-10 07:58:02 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-10 19:12:48 | 显示全部楼层
确实如此,已经改正~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-10 22:41:49 | 显示全部楼层
小甲鱼 发表于 2020-3-10 19:12
确实如此,已经改正~

活捉活甲鱼大佬
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-24 20:37:57 | 显示全部楼层
本帖最后由 bluesky0476 于 2020-4-24 20:44 编辑

         
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-29 19:36:28 | 显示全部楼层
还是发现一个bug,如果初始化一个c=Counter,一个d=Counter, 然后c.x=1,这时候c.counter是1,再给d.x=1,这时候属性名已经在字典里了,所以d.counter还是0
  1. >>> c=Counter()
  2. >>> c.x=1
  3. >>> c.y=1
  4. >>> c.counter
  5. 2
  6. >>> d=Counter()
  7. >>> d.x=4
  8. >>> d.y=5
  9. >>> d.counter
  10. 0
复制代码


试了下如果添加字典时把值也写进去就没问题了
  1. class Counter:
  2.     k = []
  3.     def __init__(self):
  4.             self.counter = 0
  5.     def __setattr__(self, name, value):
  6.             if name != 'counter':
  7.                     if name not in self.k:
  8.                             self.counter += 1
  9.                             self.k.append(name+str(value))
  10.             super().__setattr__(name, value)
  11.     def __delattr__(self, name):
  12.             self.counter -= 1
  13.             self.k.remove(name)
  14.             super().__delattr__(name)
复制代码


运行结果
  1. >>> c=Counter()
  2. >>> c.x=1
  3. >>> c.y=1
  4. >>> c.counter
  5. 2
  6. >>> d=Counter()
  7. >>> d.x=4
  8. >>> d.y=5
  9. >>> d.counter
  10. 2
  11. >>> c.z=7
  12. >>> c.counter
  13. 3
  14. >>> d.z=7
  15. >>> d.counter
  16. 3
  17. >>> c.i=5
  18. >>> c.counter
  19. 4
  20. >>> d.counter
  21. 3
  22. >>> d.i=5
  23. >>> d.counter
  24. 4
  25. >>>
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-29 19:44:22 | 显示全部楼层
但是我并不知道为什么把属性的值加上后它能区分不同对象的相同属性名,即使相同的属性名的值都是一样的。本想是把对象名和属性名打包填加到字典,但是试了半天不知道怎么把对象名传进来,就试了打包属性名和属性值,没想到可以用。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-29 20:18:18 | 显示全部楼层
本帖最后由 Ananas_Comosus 于 2020-4-29 20:24 编辑

@小甲鱼   来看看我提的问题,谢谢~~!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-29 21:59:15 From FishC Mobile | 显示全部楼层
Ananas_Comosus 发表于 2020-4-29 20:18
@小甲鱼   来看看我提的问题,谢谢~~!

你这个写法也是有个问题的例如你对同样的d. x重新赋值,会发现又多了个counter计数
你把值写进去只是把存在类属性的元素改了个名字而已,另外,这个bug怎么说呢,好像避免不了,他是存放在类属性里面的,而不是实例属性,或者可以像你的方法,改成和实例对象名绑定,应该可以解决
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-18 18:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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