Python实例化Epic类时未生成默认对象而是复制父对象属性问题
问题描述
- 我是Python新手,有一个继承自
V1Superclass的Epic类,该类可将自身实例作为子对象存入Children列表。 - 在Python控制台直接创建
Epic实例(如a = V1.Epic()、b = V1.Epic())时,实例能正确初始化默认值;但在populateChildren方法中实例化Epic对象时,新创建的childEpic并非默认实例,而是复制了父对象(self)的所有属性。 - 虽然执行
self is childEpic返回False(说明并非同一对象),但此行为不符合预期。尝试新增addChild函数在父对象作用域外实例化,问题仍存在。
相关代码
class Epic(V1Superclass): Type = 'Epic' Children = [] ParentAssetID = [] @classmethod def __init__(self, **kwargs): for key, value in kwargs.items(): if key == 'Name': self.Name = value elif key == 'Description': self.Description = value elif key == 'Super': self.Super = value elif key == 'Scope': self.Scope = value if not bool(self.Super): self.Super = None if not bool(self.Scope): self.Scope = 445082 def populateChildren(self,env,key): children = V1.utl.getChildren(env,key,'Epic',self.AssetID) for child in children: oid_type = child['_oid'].split(':')[0] if oid_type == 'Story': print('Got another backlog child') elif oid_type == 'Defect': print('Got another Defect child') elif oid_type == 'Epic': childEpic = V1.Epic() self.Children.append(childEpic)
解决方法
1. 修复类属性共享问题
Children和ParentAssetID是类属性,所有Epic实例会共用同一个列表对象。当你在父实例中添加子对象到Children,其他实例的Children也会同步变化,看起来像是子对象继承了父属性,实际是类属性被共享导致的错觉。
修复方式:把这两个属性移到__init__方法内,改为实例属性,每个实例都会拥有独立的列表:
def __init__(self, **kwargs): # 初始化实例专属的列表 self.Children = [] self.ParentAssetID = [] # 原有初始化逻辑...
2. 移除错误的@classmethod装饰器
__init__方法是实例初始化方法,不该添加@classmethod装饰器。这个装饰器会把方法的第一个参数从实例对象(self)变成类对象(cls),导致你的初始化逻辑错误地操作了类的属性状态,进而引发实例化时的属性复用问题。
修复方式:直接去掉__init__上的@classmethod:
def __init__(self, **kwargs): # 初始化逻辑...
可选:简化__init__逻辑
可以用kwargs.get()简化属性赋值代码,让逻辑更清晰:
def __init__(self, **kwargs): self.Children = [] self.ParentAssetID = [] self.Name = kwargs.get('Name') self.Description = kwargs.get('Description') self.Super = kwargs.get('Super') or None self.Scope = kwargs.get('Scope') or 445082
内容的提问来源于stack exchange,提问作者motorhead9999
相关产品推荐
相关产品推荐

