如何从嵌套列表为多个Python对象的参数赋值?
问题:通过字符串形式的对象名修改类实例属性
原始代码及报错
class thing(object): def __init__(self, data): self.name = data[0] self.spoot = data[1] self.lurmz = data[2] def __str__(self): output = f'{self.name} data → spoot: {self.spoot}, lurmz: {self.lurmz}' return output blorp_one = thing(['flarn', 750, 110]) blorp_two = thing(['gleep', 500, 70]) print(blorp_one) #<-- flarn data → spoot: 750, lurmz: 110 print(blorp_two) #<-- flarn data → spoot: 500, lurmz: 70 # data from sqlite3 db result = [['blorp_one', 'spoot', 3750], ['blorp_one', 'lurmz', 610], ['blorp_two', 'spoot', 1250], ['blorp_two', 'lurmz', 660]] result[0][0].result[0][1] = result[0][2] result[1][0].result[1][1] = result[1][2] result[2][0].result[2][1] = result[2][2] result[3][0].result[3][1] = result[3][2] # each one → AttributeError: 'str' object has no attribute 'result' print(blorp_one) #<-- desired output: flarn data → spoot: 3750, lurmz: 610 print(blorp_two) #<-- desired output: flarn data → spoot: 1250, lurmz: 660
无效尝试
tmp1 = eval(f'{result[0][0]}') tmp1.result[0][1] = result[0][2] #<-- object has no attribute 'result' tmp2 = eval(f'{result[0][1]}') tpm1.tmp2 = result[0][2] #<-- ?? doesn't error out, but doesn't change the params eval(f'{result[0][0]}').result[0][1] #<-- nope. assignment error
解决方案:用字典映射对象名与实例(推荐)
不要直接通过字符串操作变量名,最安全高效的方式是提前创建一个字典,将对象名字符串映射到对应的实例:
class thing(object): def __init__(self, data): self.name = data[0] self.spoot = data[1] self.lurmz = data[2] def __str__(self): output = f'{self.name} data → spoot: {self.spoot}, lurmz: {self.lurmz}' return output blorp_one = thing(['flarn', 750, 110]) blorp_two = thing(['gleep', 500, 70]) # 创建对象映射字典 obj_map = { 'blorp_one': blorp_one, 'blorp_two': blorp_two } # 数据库返回的数据 result = [['blorp_one', 'spoot', 3750], ['blorp_one', 'lurmz', 610], ['blorp_two', 'spoot', 1250], ['blorp_two', 'lurmz', 660]] # 遍历数据修改属性 for obj_name, attr_name, value in result: target_obj = obj_map[obj_name] setattr(target_obj, attr_name, value) # 验证结果 print(blorp_one) # 输出: flarn data → spoot: 3750, lurmz: 610 print(blorp_two) # 输出: gleep data → spoot: 1250, lurmz: 660
替代方案:通过globals()获取全局变量(不推荐)
如果对象是全局变量,可以通过globals()字典直接获取,但这种方式风险较高(容易误操作全局变量,若数据不可信还可能引发安全问题):
for obj_name, attr_name, value in result: target_obj = globals()[obj_name] setattr(target_obj, attr_name, value)
错误原因解析
- 直接操作字符串:
result[0][0]是字符串'blorp_one',字符串没有result属性,因此result[0][0].result[0][1]会抛出AttributeError。 - eval使用错误:
eval(f'{result[0][0]}')确实能获取到实例,但你错误地尝试修改实例的result属性,而实际需要修改的是spoot或lurmz这类实例属性。 - 字符串赋值误解:
tpm1.tmp2 = result[0][2]只是给实例添加了一个名为tmp2的新属性,并非修改目标属性spoot/lurmz。
内容的提问来源于stack exchange,提问作者WhiteRau
相关产品推荐
相关产品推荐

