类外函数设置对象属性存入字典后未生效问题及解决办法
问题分析与解决方案
嘿,我来帮你捋清楚这个问题!首先得明确:这跟垃圾回收完全没关系,问题出在你给对象设置属性的方式上。
为什么会拿到默认值?
你看这段循环代码:
for attr in kwargs.keys(): temp.attr=kwargs[attr] print temp.attr,kwargs[attr]
这里的temp.attr写法有问题——Python会把.attr当成一个固定的属性名,也就是说你每次循环都是在给temp对象创建/赋值一个叫attr的属性,而不是你想要的a、b、c这些属性。
举个例子,当attr是'a'时,你实际执行的是temp.attr = 1,而不是temp.a = 1。原来的temp.a还是初始化时的默认值0,自然打印出来是默认值。
修复代码
把属性赋值的方式改成用setattr()函数,它能根据变量动态设置属性名:
class Logpkt(): def __init__(self): self.a=0 self.b='' self.c='' self.d='' self.e='' self.f='' self.g='' self.h='' self.i='' self.j='' self.k='' def set_class(**kwargs): temp = Logpkt() print(kwargs) for attr, value in kwargs.items(): # 直接遍历键值对更高效 setattr(temp, attr, value) print(getattr(temp, attr), value) # 用getattr获取动态属性 return temp obj={} obj[1]=set_class(a=1,b=2) obj[2]=set_class(c=1,d=2) print(obj[1].a) # 现在会输出1 print(obj[2].c) # 现在会输出1
更优的实现方式
其实你完全可以不用单独写set_class函数,直接在类的__init__方法里处理关键字参数,代码会更简洁:
方案1:优化__init__方法
class Logpkt(): def __init__(self, **kwargs): # 先设置所有默认值 self.a = 0 self.b = '' self.c = '' self.d = '' self.e = '' self.f = '' self.g = '' self.h = '' self.i = '' self.j = '' self.k = '' # 用传入的参数覆盖默认值 for attr, value in kwargs.items(): setattr(self, attr, value) # 使用时直接创建对象 obj = {} obj[1] = Logpkt(a=1, b=2) obj[2] = Logpkt(c=1, d=2) print(obj[1].a) print(obj[2].c)
方案2:用dataclass(Python3.7+推荐)
如果你的Python版本是3.7及以上,用dataclasses模块能让代码更简洁优雅,自动帮你处理初始化、属性设置等逻辑:
from dataclasses import dataclass @dataclass class Logpkt(): a: int = 0 b: str = '' c: str = '' d: str = '' e: str = '' f: str = '' g: str = '' h: str = '' i: str = '' j: str = '' k: str = '' # 使用方式超简单 obj = {} obj[1] = Logpkt(a=1, b=2) obj[2] = Logpkt(c=1, d=2) print(obj[1].a) print(obj[2].c)
内容的提问来源于stack exchange,提问作者varun jana
相关产品推荐
相关产品推荐

