如何防止父类的实例变量被python中的子类覆盖?

时间:2017-02-03 00:15:39

标签: python inheritance

我在下面写了两个非常简单的类。 Human继承自Mammal类。当我致电print(jo.drinkMe("sage"))时,我希望"生病"打印,但是#34;罚款"打印出来。我认为self.problem类中的Human会覆盖self.problem类中的Mammal。我需要对我的代码做什么才能使最后的print语句打印出来" sick"?

class Mammal:
    def __init__(self):
        self.problem = "sage"
        self.result = "sick"

    def drinkMe(self,tea):
        if tea == self.problem:
            return self.result
        else:
            return "fine"

class Human(Mammal):
    def __init__(self):
        super().__init__()
        self.problem = "paint"
        self.result = "die"
    def drinkMe(self,tea):
        if tea == self.problem:
            return self.result
        else:
            return super().drinkMe(tea)

jo = Human()
to = Mammal()
print(jo.drinkMe("sage"))

3 个答案:

答案 0 :(得分:2)

您遇到的问题是Mammal仅在实例化时设置其实例属性problemresultjo = Human()实例化一个Mammal对象,但随后将problemresult属性破坏为自己的属性。要详细,你有:

class Human(Mammal):
    def __init__(self):
        super().__init__()
        # calls `Mammal.__init__()`, which sets
        # self.problem = "sage"
        # self.result = "sick"
        self.problem = "paint"
        self.result = "die"
        # overwrites what `Mammal.__init__()` did a
        # couple lines ago.
   ...

您可以改为:

class Mammal(object):
    problem = "sage"
    result = "sick"

    def drink_me(self, tea):
        if tea == self.problem:
            return self.result
        else:
            return "fine"


class Human(Mammal):
    problem = "paint"
    result = die

    def drink_me(self, tea):
        if tea == self.problem:
            return self.result
        else:
            return super().drink_me(tea)

答案 1 :(得分:2)

我希望这会有所帮助。这是一种与原始代码略有不同的思维方式,但老实说,您发布的代码需要一些凌乱的super()调用。我认为您的目标是Mammal()的子类,其中包含来自drinkMe()的结果的其他选项

采取这种方法怎么样:所有Mammals现在都有一个包含饮料和结果的字典。子类使用自己对饮料的自定义响应更新此字典。这样你就有了一个只返回饮料响应的功能。如果一个实例喝了没有设置响应的东西会怎么样?现在,您只需要在drinkMe()内添加异常处理。

class Mammal:
    def __init__(self):
        self.problems = {'sage': 'sick'}

    def drinkMe(self, tea):
        return self.problems[tea]


class Human(Mammal):
    def __init__(self):
        super().__init__()
        self.problems.update({'paint': 'die'})

jo = Human()
print(jo.drinkMe("sage"))

修改:详细说明原始代码打印fine而不是sick的原因。

当您设置名为Human的{​​{1}}时,jo设置为jo.problem。因此,paint调用jo.drinkMe,再次检查是否super.drinkMe。但请记住,您仍然没有更改tea == self.problem 。它仍设置为jo.problem,因此返回paint

fine是实例本身,在这种情况下是self,当您致电jo时,super.drinkMe()不会再次投放,因此super.__init__()仍然设置为它是什么。

答案 2 :(得分:0)

我找到了一种非常简单的方法来阻止Human中声明的实例变量覆盖Mammal中的实例变量。代码基本上只是在每次调用self.problem时重新分配self.resultdrink_me的值:

class Mammal:

    def __init__(self):
        self.problem = "sage"
        self.result = "sick"

    def drinkMe(self,tea):
        if tea == self.problem:
            return self.result
        else:
            return "fine"
class Human(Mammal):
    def __init__(self):
        super().__init__()
        self.problem = "paint"
        self.result = "die"
    def drinkMe(self,tea):
        result = ''
        if tea == self.problem:
            return self.result
        else:
            super().__init__()
            result = super().drinkMe(tea)
            self.__init__()
            return(result)
jo = Human()
print(jo.drinkMe("sage"))
print(jo.drinkMe("paint"))

此代码首先打印'病态'然后'死'。