Python:子项继承父级默认值(如果未指定)

时间:2014-02-25 19:38:05

标签: python-2.7 dictionary initialization multiple-inheritance super

相当中级的程序员,但Python初学者在这里。我已经做了一段时间的游戏,昨天我重新组织了所有的课程。我最初只使用组合数据结构,我现在使用两者的混合。当我想要产生播放器时,我的问题就来了。这是相关的代码。

class Object(object):
    def __init__(self, **kwargs):
        DeaultValues={'x':0, 'y':0, 'name':None, 'texture':None, 'blocks':False, 'ObjectID':None, 'Fighter':None, 'Corpse':None, 'Skill':None, 'ai':None}
        for key,value in DeaultValues.items(): 
            try: 
                vars(self)[key] = kwargs[key]
            except ValueError: 
                vars(self)[key] = value
            except KeyError:
                vars(self)[key] = value
        self.x = kwargs['x']
        self.y = kwargs['y']
        self.name=kwargs['name']
        self.blocks=kwargs['blocks']
        self.ObjectID=self.AttachID()
        self.texture = kwargs['texture']

        #This section binds an actors compenents to itself
        self.Corpse = kwargs['Corpse']
        if self.Corpse:
            self.Corpse.owner = self
        self.Skill=kwargs['Skill']
        if self.Skill:
            self.Skill.owner = self
        self.Fighter = kwargs['Fighter']
        if self.Fighter:
            self.Fighter.owner = self
        self.ai = kwargs['ai']
        if self.ai:
            self.ai.owner = self

class HighActor(Object):
    def __init__(self, **kwargs):
        super(HighActor, self).__init__(**kwargs)

class Player(HighActor):
    def __init__(self, Level=1, Xp=0, PreviousLevel=0, PreviousLevelThreshold=100, LevelThreshold=500, **kwargs):
        super(Player, self).__init__(**kwargs)
        self.LevelThreshold = LevelThreshold
        self.PreviousLevelThreshold=PreviousLevelThreshold
        self.PreviousLevel=PreviousLevel
        self.Level = Level
        self.Xp = Xp

def SpawnPlayer():
    global player
    FighterComponent = Fighter(MaxHp=100, Hp=100, IsHasted=[False, False], death_function=None)
    CorpseComponent = Corpse()
    SkillComponent = HighActorSkill()
    player=Player(name="player", x=None, y=None, texture="player.png", blocks=True, ObjectID=None, Fighter=FighterComponent, Corpse=CorpseComponent, Skill=SkillComponent, ai=None)

上面的代码工作正常,但它并没有真正继承任何东西。为了使播放器对象不出错,我必须添加以将基础对象类的所有属性添加到播放器初始化。如果我删除了player = Player()语句中设置为none的任何值,则会出现值错误或键错误。我尝试通过使用默认值的dict来纠正这个问题,这些默认值循环遍及所有给定的kwargs,如果它们没有值,则将它们设置为默认值。这一直有效,直到我找到任何组件。所以在没有指定ai = none的情况下,我得到了关键错误。我真的很想让我的代码采用这样的格式,如果我没有为任何基础对象类属性指定值,则会传入默认值,但如果我确实指定了一个值,则会将其传递给基类。我理想的最终结果是让我的播放器实例看起来像这样:

def SpawnPlayer():
    global player
    FighterComponent = Fighter(MaxHp=100, Hp=100, IsHasted=[False, False], death_function=None)
    CorpseComponent = Corpse()
    SkillComponent = HighActorSkill()
    player=Player(name="player", texture="player.png", blocks=True, Fighter=FighterComponent, Corpse=CorpseComponent, Skill=SkillComponent)

我怀疑我的继承不能100%工作,因为如果我遗漏了ObjectID就会出错,即使应该分配,因为在低音类的init中它的设置等于getid(self)。所以我要么继承我的遗产问题(我真的在与Super挣扎),或者我的对象的签名,我不太确定我的问题是什么,更重要的是为什么。我并不反对大幅改变代码签名,因为我还在编写引擎,所以没有任何依赖于此。该怎么办?

1 个答案:

答案 0 :(得分:3)

我认为你的班级结构应该是不同的。每个类应该只具有它需要的属性,在构建继承时添加新的属性,例如:

class Object(object):

    def __init__(self, x=0, y=0, name=None, **kwargs):
        self.x = x
        self.y = y
        self.name = name


class HighActor(Object):

    def __init__(self, corpse=None, skill=None, **kwargs):
        super(HighActor, self).__init__(**kwargs)
        self.corpse = corpse
        self.skill = skill


class Player(HighActor):

    def __init__(self, level=1, xp=0, **kwargs):
        super(Player, self).__init__(**kwargs)
        self.level = level
        self.xp = xp

在每个级别指定属性 - 所有Object应该包含xyname,所有HighActor应该 corpseskill等。现在您可以指定要提供给层次结构的三个级别中的任何一个的参数,或者将它们保留为默认值:

player = Player(name="player one", skill=100, xp=12) 

您可能有不适合此继承方案的内容 - 在模型中拥有多个单独的继承关系集是可以的,不要强制它!


这是有效的,因为每个**kwargs末尾的__init__“删除”方法不期望进入字典kwargs的任何关键字参数,然后可以将它们全部传递更上一层楼。执行此操作时,super(...).__init__(**kwargs)会将字典解压缩回关键字参数,任何不存在的字典都将采用指定的默认值。