python 面向对象 修改对象属性不生效

问题描述

我创建了一个类,其中 self.attributes 是一个字典属性,当我试图为他的元素添加属性时,发现并不能添加成功。下面是代码和报错:
self.attributes 的结构

def set_attributes(self, nodes, attributes=None):

        # ... some code 

        if attributes is None:
            self.attributes = {
                "IS": {"layer": 6},
                "OS": {"layer": 6},
                "BC": {"layer": 6},
                "DC": {"layer": 6},
                "CC": {"layer": 6},
                "E": {"layer": 6},
            }
        # ... some code

    def set_attribute_probability(self):
        for key in self.attributes.keys():
            print(key)
            self.attributes[key]['p'] = [len(item) / len(self.nodes)
                                         for item in self.attributes[key]["cluster"]]
            print(self.attributes[key]['p'])
        print(self.attributes['IS']['p'])

        """
        for attr_values in self.attributes.values():
            attr_values['p'] = [len(item) / len(self.nodes)
                                for item in attr_values["cluster"]]
        """

我在 set_attribute_probability 方法中遍历 self.attributes 属性,并为其各元素添加p 属性。但遍历添加完成后,我试图访问其中一个属性的 p,结果报错 KeyError。可以看到当我在循环中设置完毕 p 后立马访问是没有问题的,但在循环外访问就报错了,我不理解。

报错截图
image.png

补充

  • self.attributes 中的 cluster 属性是通过其他方法计算的,因为计算比较耗时所以第一次计算完就存在了文件中,所以 self.attributes 除了第一块代码设置外还可能从文件读出来,不知道和这个有没有关系。
  • 不知道 pyton 面向对象属性更新的机制是什么,可以看到我第二块代码注释掉的部分,我开始以为是 attr_values 是 copy 的所以修改不生效,所以特地换了键值来修改,但还是报错。

请大佬解惑!

阅读 3.3k
1 个回答

非常感谢 @chaleaoch 的提醒,具体原因我已经在问题评论回复了:

问题可能在于我将 nodes 属性设置为了 @property 并在该属性方法中修改了 attributes 属性。结果代码中每次调用 len(self.nodes) 时都会将 attributes 重置,这也解释了为什么我打印最后一个属性 Ep 属性时是成功的(因为在设置完该属性的 p 后没有再调用 self.nodes 了)。

这提醒我在编写属性方法时,仅编写有关该属性的代码,不要引入具有副作用的代码,以免出现难以排查的 Bug。

再次感谢 @chaleaoch !

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题