Python类中属性列表初始化与动态生成的差异原因解析
这问题抓得特别准,刚好涉及到Python里不可变对象的引用特性和代码执行时机的差异,咱们一步步理清楚:
先看Case 1的问题根源
在__init__方法里,你执行self.tooldetails = [self.name, self.manufacturer]的时候,是把当时self.name和self.manufacturer指向的字符串对象的引用存进了列表里。
但字符串是Python的不可变对象——当你后续执行tool1.name = 'abc'时,并不是修改原来的"defaultname"字符串,而是创建了一个新的字符串"abc",然后让self.name这个变量指向这个新对象。而列表tooldetails里存的还是原来那个"defaultname"的引用,所以调用get_details()时,返回的还是旧值。
简单说:列表里存的是“快照”,不是“实时链接”。
再看Case 2为什么能正常工作
Case 2里,你把self.tooldetails的创建放到了_set_detail_list方法里,而且每次调用get_details()都会先执行这个方法。这意味着:
- 每次调用
get_details()时,都会重新获取当前self.name和self.manufacturer指向的最新对象的引用,再放进列表里。 - 所以当你修改了
tool1.name之后,再调用get_details(),拿到的就是更新后的"abc"了。
(顺便提一句:Case 2的代码里get_details方法里的_set_detail_list()应该改成self._set_detail_list(),不然会报未定义的错误,你可能是手滑打错了😉)
额外的优化建议:用@property实现自动同步
如果想让tooldetails始终自动同步最新的属性值,不用手动调用_set_detail_list,可以用Python的@property装饰器把它变成动态计算的属性:
class Tools(): def __init__(self): self.name = "defaultname" self.manufacturer = "defaultmanuf" @property def tooldetails(self): # 每次访问这个属性时,都会重新生成列表 return [self.name, self.manufacturer] def get_details(self): return self.tooldetails
这样不管你什么时候访问tool1.tooldetails或者调用get_details(),拿到的都是当前最新的属性值,完全不用手动维护列表的更新,而且分组管理也很灵活——比如你可以定义多个@property,比如basic_details、advanced_details,分别包含不同的属性组合,比自省方法可控多了。
内容的提问来源于stack exchange,提问作者Xarris Kor

