十月故里 发表于 2020-3-9 20:33:40

045讲最后一题小甲鱼做错了

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

今天做到45讲习题的时候,提交之后可以看答案嘛,然后我提交的正是最后一题的答案,里面我举了两个例子,一个错误一个正确的,然后神奇的发现,小甲鱼最后一道题的答案和我错误的例子有点像
首先看看题目
2. 修改上边【测试题】第 4 题,使之可以正常运行:编写一个 Counter 类,用于实时检测对象有多少个属性。
class Counter:
        def __init__(self):
                self.counter=-1
        def __setattr__(self,name,value):
                super().__setattr__(name,value)
                super().__setattr__('counter',self.counter+1)
        def __delattr__(self,name):
                self.counter-=2
                super().__delattr__(name)
这是我刚看到题写的第一个写法,然后检查的时候发现,只要调用到setattr的时候,counter都会+1,所以当我们对一个已存在的属性重新赋值的时候,又会导致counter+1了
>>> c=Counter()
>>> c.x=1
>>> c.x=2
>>> c.counter
2
所以我加了个if来判断
class Counter:
        k=[]
        def __init__(self):
                self.counter=0
        def __setattr__(self,name,value):
                if name != 'counter':
                        if name not in self.k:
                                self.counter+=1
                                self.k.append(name)
                super().__setattr__(name,value)
        def __delattr__(self,name):
                self.counter-=1
                self.k.remove(name)
                super().__delattr__(name)
此时就可以正常统计这个实例对象究竟创建了多少个属性啦
>>> c=Counter()
>>> c.x=1
>>> c.x=2
>>> c.counter
1
>>> c.y=2
>>> c.counter
2
>>> del c.x
>>> c.counter
1

zltzlt 发表于 2020-3-10 07:58:02

@小甲鱼

小甲鱼 发表于 2020-3-10 19:12:48

确实如此,已经改正~

十月故里 发表于 2020-3-10 22:41:49

小甲鱼 发表于 2020-3-10 19:12
确实如此,已经改正~

活捉活甲鱼大佬{:5_109:}

bluesky0476 发表于 2020-4-24 20:37:57

本帖最后由 bluesky0476 于 2020-4-24 20:44 编辑

         {:10_257:}

Ananas_Comosus 发表于 2020-4-29 19:36:28

还是发现一个bug,如果初始化一个c=Counter,一个d=Counter, 然后c.x=1,这时候c.counter是1,再给d.x=1,这时候属性名已经在字典里了,所以d.counter还是0
>>> c=Counter()
>>> c.x=1
>>> c.y=1
>>> c.counter
2
>>> d=Counter()
>>> d.x=4
>>> d.y=5
>>> d.counter
0

试了下如果添加字典时把值也写进去就没问题了
class Counter:
    k = []
    def __init__(self):
            self.counter = 0
    def __setattr__(self, name, value):
            if name != 'counter':
                  if name not in self.k:
                            self.counter += 1
                            self.k.append(name+str(value))
            super().__setattr__(name, value)
    def __delattr__(self, name):
            self.counter -= 1
            self.k.remove(name)
            super().__delattr__(name)


运行结果
>>> c=Counter()
>>> c.x=1
>>> c.y=1
>>> c.counter
2
>>> d=Counter()
>>> d.x=4
>>> d.y=5
>>> d.counter
2
>>> c.z=7
>>> c.counter
3
>>> d.z=7
>>> d.counter
3
>>> c.i=5
>>> c.counter
4
>>> d.counter
3
>>> d.i=5
>>> d.counter
4
>>>

Ananas_Comosus 发表于 2020-4-29 19:44:22

但是我并不知道为什么把属性的值加上后它能区分不同对象的相同属性名,即使相同的属性名的值都是一样的。本想是把对象名和属性名打包填加到字典,但是试了半天不知道怎么把对象名传进来,就试了打包属性名和属性值,没想到可以用。

Ananas_Comosus 发表于 2020-4-29 20:18:18

本帖最后由 Ananas_Comosus 于 2020-4-29 20:24 编辑

@小甲鱼   来看看我提的问题,谢谢~~!

十月故里 发表于 2020-4-29 21:59:15

Ananas_Comosus 发表于 2020-4-29 20:18
@小甲鱼   来看看我提的问题,谢谢~~!

你这个写法也是有个问题的例如你对同样的d. x重新赋值,会发现又多了个counter计数
你把值写进去只是把存在类属性的元素改了个名字而已,另外,这个bug怎么说呢,好像避免不了,他是存放在类属性里面的,而不是实例属性,或者可以像你的方法,改成和实例对象名绑定,应该可以解决
页: [1]
查看完整版本: 045讲最后一题小甲鱼做错了