Python类实例添加至列表属性被覆盖问题及代码优化咨询
问题分析与解决方案
a) 为什么set_pos赋值后返回None?
其实原因很直白:你的set_pos方法没有写显式的return语句。在Python里,任何函数或方法如果没有指定返回值,默认都会返回None。你调用instance.set_pos(i, k)时,这个方法只是修改了当前实例的x和y属性,并没有返回任何内容,所以把它赋值给special_class变量,得到的自然就是None啦。
b) 代码优化建议
你的代码里有不少可以简化和规范的地方,我挑核心点说:
- 别用内置类型名当变量名:比如你用了
dict,这会覆盖Python的内置字典类型,建议改成char_to_class这类有意义的名字。 - 删掉冗余的嵌套循环:你不需要嵌套遍历字典的键,直接通过字符串里的字符去字典里查对应的类就好,代码会简洁很多。
- 去掉重复的
special_instance代码段:你已经通过instance.set_pos(i, k)修改了当前实例的坐标,完全没必要再从字典里重新取一遍实例再调用一次set_pos,这属于重复操作。 - 统一实例创建逻辑:把字典里的实例换成类本身,每次需要的时候创建新实例,这也能顺便解决后面的坐标覆盖问题。
c) 坐标被覆盖的原因及修复方案
原因
你现在的字典里存的是已经创建好的单个实例,比如dict["X"] = special_class(),不管你从字典里取多少次"X"对应的对象,都是同一个special_class实例。每次调用set_pos都是在修改这个唯一实例的坐标,最后列表里所有的X对应的其实都是同一个对象,坐标自然会被最后一次的设置覆盖。
修复方案
把字典里存储的实例改成类本身,这样每次需要的时候,我们都创建一个新的实例,每个实例都是独立的个体,修改坐标不会互相影响。
完整优化代码
class SpecialClass: # 类名建议用大驼峰命名法,符合Python编码规范 def __init__(self): self.char = "X" def set_pos(self, x, y): self.x = x self.y = y def get_pos(self): return (self.x, self.y) class NormalClass: def __init__(self): self.char = "Y" class AlsoSpecialClass: def __init__(self): self.char = "Z" def set_pos(self, x, y): self.x = x self.y = y def get_pos(self): return (self.x, self.y) string = "XYXZ" # 字典存储类,而不是提前创建好的实例 char_to_class = {"X": SpecialClass, "Y": NormalClass, "Z": AlsoSpecialClass} ls = [] for idx, char in enumerate(string): # 每次循环都创建新的实例 cls = char_to_class[char] instance = cls() # 判断是否需要设置坐标 if char in ("X", "Z"): # 直接调用set_pos修改当前实例的坐标,不需要赋值 instance.set_pos(idx, idx) # 这里可以根据你的需求调整参数,我暂时用字符串索引替代原逻辑的k ls.append(instance) print("Position after finished loop") print(ls[0].get_pos()) # 输出(0, 0) print(ls[2].get_pos()) # 输出(2, 2)
内容的提问来源于stack exchange,提问作者Sov
相关产品推荐
相关产品推荐

